面向对象封装,相关的函数放到一个对象中,便于管理
def main():
# server_socket = init_server()
# run_server(server_socket)
tcp_server = WebServer()
tcp_server.run_server()
class WebServer(object):
def run_server(self):
"""运行服务"""
# 设置server_socket的非堵塞状态
self.server_socket.setblocking(False)
# 使用客户端列表接收新的客户端
clients = list()
# 循环接收客户请求
while True:
# 使用非堵塞时,会报错,用try进行捕获异常
try:
# 从三次握手的队列中取出一个客户端关联的套接字
client, addr = self.server_socket.accept()
# client_run(client)
print(client)
# 将新接收的客户端放到客户端列表中
clients.append(client)
# 设置客户端的非堵塞状态
client.setblocking(False)
except Exception as e:
pass
# 循环取出客户端,查看是否有数据
for client_new in clients:
# 捕获client的非堵塞状态时产生的异常
try:
# 接收客户端发送过来的数据
data = client_new.recv(1024).decode()
# 判断是否有数据
if data: # 有数据
# 处理一个客户端的请求
self.client_run(client_new, data)
else: # 没有数据
client_new.close() # 关闭没有数据的客户端套接字
clients.remove(client_new) # 将没有数据的客户端从列表中删除
except Exception as e:
pass
# 关闭套接字
self.server_socket.close()
def client_run(self, client,data):
"""处理一个客户端请求"""
# 接收数据
# print(client)
# time.sleep(10)
# data = client.recv(1024).decode()
# 将接收的数据分割为以每一行作为一个元素的列表
header_lines = data.splitlines()
try:
header_line = header_lines[0]
print(header_line)
res = re.match(r"[^/]+([^ ]*)", header_line)
# 判断是否匹配
if res: # 匹配了
file = res.group(1)
# 如果是"/",则是在访问首页"index.html"
if file == "/":
file = "/index.html"
except Exception as e:
print(e)
try:
# 发送数据
with open("./html%s" % file, "rb") as f:
body = f.read()
header = "HTTP/1.1 200 0K\r\n"
# http头部字段告诉浏览器接收多少字节结束本次数据的传输
# Content-Length:xxx\r\n
header += "Content-Length:%d\r\n" % len(body)
content = header + "\r\n"
client.send(content.encode("utf-8"))
client.send(body)
except Exception as e:
print(e)
header = "HTTP/1.1 404 NOT FIND\r\n"
body = "页面不见了"
content = header + "\r\n" + body
client.send(content.encode("utf-8"))
# 关闭套接字
# client.close()-----------注释掉关闭客户端,就是长连接
def __init__(self):
"""创建tcp套接字"""
# 创建tcp服务器端套接字
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置套接字地址选项
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定本地端口
self.server_socket.bind(("", 9999))
# 变为被动套接字
self.server_socket.listen(128)
# return server_socket
if __name__ == '__main__':
main()