轮询的方法接收数据,效率低,套接字越多,需要的时间越长
代码:
1 import socket 2 import re 3 4 5 def client_msg(new_client,recv_data): 6 # 接收客户端请求 7 # recv_data = new_client.recv(1024).decode("utf-8") 8 # 把读出的数据分行 9 recv_data_lines = recv_data.splitlines() 10 # 正则匹配GET后面的请求的页面 11 # [^/]表示非“/”字符 +表示至少1个或多个,[^ ]只要不是空格,*表示0个或多个 12 ret = re.match(r"[^/]+(/[^ ]*)",recv_data_lines[0]) 13 14 # ret = re.search(r"/[^ ]*",recv_data_lines[0]) # 查找第一次“/”后面非空格的字符串 15 file_name = ret.group(1) 16 # 打开文件 17 try: 18 f = open("./html" + file_name,"rb") 19 except: 20 # 创建返回数据 HEADER 21 response = "HTTP/1.1 404 NOT FOUND\r\n" 22 response += "\r\n" 23 response += "-----NOT FOUND----" 24 # 发送数据到客户端 25 new_client.send(response.encode("utf-8")) 26 else: 27 # 读出数据 28 html_content = f.read() 29 # 把读出的数据放到BODY体里面 30 response_body = html_content 31 32 # 创建返回数据 HEADER 33 response_header = "HTTP/1.1 200 ok\r\n" 34 # 告诉浏览器发送过去的长度 35 response_header += "Content-Length:%d\r\n" % len(response_body) 36 response_header += "\r\n" 37 # 把HEADER和BODY拼接在一起 38 response = response_header.encode("utf-8") + response_body 39 # 发送数据到客户端 40 new_client.send(response) 41 42 # 关闭套接字 长链接不要关闭此套接字 等客户端关闭 43 # new_client.close() 44 45 46 def main(): 47 # 创建套接字 48 tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 49 # 设置当服务器先调用close() 即服务器4次回收之后资源能够立即释放,这样就保证了下次运行程序时,可以立即使用 50 # SO_REUSEADDR重复使用地址 51 tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 52 # 绑定端口 53 tcp_server_socket.bind(("",7890)) 54 # 设置监听状态 55 tcp_server_socket.listen(128) 56 # 设置非堵塞 57 tcp_server_socket.setblocking(False) 58 59 # 新建socket存储列表 60 new_client_list = list() 61 62 # 新建为客户端服务的套接字 63 while True: 64 try: 65 new_client,client_addr = tcp_server_socket.accept() 66 except Exception as ret: 67 pass 68 else: 69 # 新套接字设置非堵塞 70 new_client.setblocking(False) 71 # 把新套接字放入客户端服务套接字列表 72 new_client_list.append(new_client) 73 # 遍历套接字列表,循环查看有没有数据过来 ----轮询 74 for new_client_socket in new_client_list: 75 try: 76 # 如果有数据,就接收并解码 77 recv_data = new_client_socket.recv(1024).decode("utf-8") 78 except Exception as ret: 79 # 如果没数据就抛出异常 pass处理 80 pass 81 else: 82 # 接收的如果是客户的请求数据 83 if recv_data: 84 # 调用客户端服务 85 client_msg(new_client_socket,recv_data) 86 # 如果是客户端调用close() 则关闭套接字移出列表 87 else: 88 new_client_socket.close() 89 # 移出列表节省资源 90 new_client_list.remove(new_client_socket) 91 92 # 关闭套接字 93 tcp_server_socket.close() 94 95 96 if __name__ == '__main__': 97 main()