0%

Python基础--函数版搭建简单WebServer

Python基础–函数版搭建简单WebServer

大致代码思路如下
1.初始化socket
2.端口复用
3.bind端口
4.listen打开监听
5.循环接受请求
6.处理客户请求
7.发送客户请求
8.关闭服务客户端的端口
9.关闭服务端

==Tips:这个代码是面向函数版的,之后会把面向对象的写出来,当前代码,经过了去重(重构),函数化和动静分离.所以如果有需要的可以在详细看下==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import socket


def client_exec(client):
# 获取接受的数据
data = client.recv(1024)

# 看看data是否有数据.有数据的时候才会处理,没数据直接退出客户端
if data:
# 对数据进行解码
decode_data = data.decode('utf-8')
print(decode_data)

# 对获取到的数据进行切割,得到对应的访问路径
split_data = decode_data.split(' ', maxsplit=2)

# 异常判断,如果切割数据有异常,则直接关闭客户端.
# 因为服务端不清楚,是否正确获取到路径,以防客户输入有误,或者放置入侵添加异常处理
try:
file_path = split_data[1]
if file_path == "/":
file_path = "/index.html"
except Exception as e:
print("异常是 ", e)
client.close()
return

else:
client.close()
return

# 进行动静分离.目前首先以后缀名进行区分
# 简单区分:
# 动态文件: html
# 静态文件: 图片,音频,视频,大文本
# 使用函数,endswith取出后缀名进行判断
# 这里暂时只设置html是动态资源,其他都是静态.如果有其他需求的话,可以再添加elif进行判断.或者使用正则表达式进行比配也行
if file_path.endswith(".html"):

# 代码重构,把指定的重复部分,添加至头部
reponse_line = "http/1.1 200 OK\r\n"
reponse_header = ""
reponse_empty = '\r\n'
# 根据获取的数据进行返回内容
if file_path == '/post.html':
# 异常判断,打开文件,如果文件异常,返回异常信息,关闭连接
# 这个是对应html文件的打开,只写了一个例子,下面elif都是文本输出
try:
with open("./123.html", encoding='utf-8') as f:
reponse_body = f.read()
except Exception as e:
print("123.html异常:", e)
client.close()
return

elif file_path == '/index.html':
reponse_header = "content-type:text/html;charset= utf-8\r\n"
reponse_body = '你好,这个是index界面'
else:
# 设置404错误界面,如果不是匹配上面的,就直接放回404页面
reponse_line = "http/1.1 404 not found\r\n"
# 回应头,添加指定的编码信息
reponse_header = "content-type:text/html;charset= utf-8\r\n"
# 空行
reponse_empty = "\r\n"
reponse_body = '你好,这个是错误界面'

# 代码重构(去重)将冗余代码进行缩减,填写至公共部分
reponse_conten = reponse_line + reponse_header + reponse_empty + reponse_body
client.send(reponse_conten.encode("utf-8"))
client.close()
return
else:
# file_path.endswith(".jpg|png|jpeg"):
del_image(client, file_path)

client.close()


def del_image(client, file_path):
"""
静态资源处理
:param client: 传参的客户端所有信息
:param file_path: 客户端的访问路径
:return:
"""
try:
reponse_line = "http/1.1 200 OK \r\n"
# 回应头
reponse_header = ""
# 空行
reponse_empty = '\r\n'
# 打开文件
with open('.%s' % file_path, "rb") as f:
creponse = f.read()
reponse_conten = reponse_line.encode("utf-8") + reponse_header.encode("utf-8") + reponse_empty.encode(
"utf-8") + creponse
client.send(reponse_conten)
except Exception as e:
print("错误是:", e)
reponse_404_html(client)


def reponse_404_html(client):
"""
设置返回404的界面
:param client:
:return:
"""
reponse_line = "http/1.1 404 not found\r\n"
# 回应头
reponse_header = "content-type:text/html;charset= utf-8\r\n"
# 空行
reponse_empty = "\r\n"
reponse_body = '错误'
reponse_conten = reponse_line + reponse_header + reponse_empty + reponse_body
client.send(reponse_conten.encode("utf-8"))


def main():
"""
主函数运行程序
:return:none
"""
# 初始化tcp套接字
server_socket = init_tcp()

# 处理客户换请求
del_client(server_socket)

# 关闭客户端
server_socket.close()


def del_client(server_socket):
# 循环接受处理客户请求
while True:
# 获取指定的客户端信息和地址
client, address = server_socket.accept()
print(client)

# 处理客户请求
client_exec(client)


def init_tcp():
"""
初始化socket,设置端口复用
:return: server_socket
"""
# 初始化socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# bind端口
server_socket.bind(('', 8080))
# 设置端口监听
server_socket.listen(128)
return server_socket


if __name__ == '__main__':
main()