知识点:1、使用多线程,多进程,协程完成web并发服务器 2、单进程-单线程-非堵塞也可以实现并发服务器
1、多进程和协程的代码在下面注释掉的部分,我把三种写在一起了
import socket import re import threading import multiprocessing import gevent """服务器收发数据""" def web_server(new_socket): datas = new_socket.recv(1024).decode('utf-8') # 接收浏览器请求的数据 print(datas) data1 = datas.splitlines() res = re.match("[^/]+(/[^ ]*)", data1[0]) # 使用正则获取到请求头部中的的第一行中的请求地址对象 if res: # 判断如果请求地址有内容 file_name = res.group(1) # 获取正则对象中的内容 if file_name == '/': # 如果地址是‘/’,也就是请求地址后面没有带指的页面,即主页 file_name = '/index.html' try: data = open('./html'+file_name,'rb') # 获取请求的资源在服务器中的文件 except: data_body = 'HTTP 404 NOT FOUND/1.1\r\n' # 服务器发送消息的头部需要换行,用\r\n data_body += '\r\n' # 头部和body需要空一行 data_body += '<h1>not found</h1>' # 服务器没找到浏览器需要的资源,返回的html页面 new_socket.send(data_body.encode('utf-8')) # 发送给浏览器 else: data_head = 'HTTP 200 OK/1.1\r\n' # 请求成功,服务器返回200 data_head += '\r\n' data_body = data.read() data.close() # 关闭文件 new_socket.send(data_head.encode('utf-8')) new_socket.send(data_body) new_socket.close() # 关闭新的客户端套接字
"""主程序入口""" def main(): tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建套接字 tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 防止下一次使用该服务器端口被占用情况 tcp_socket.bind(('127.0.0.1', 7789)) # 服务器绑定地址和端口 tcp_socket.listen(128) # 监听套接字 while True: new_socket, adrees = tcp_socket.accept() # 1、多进程实现并发服务 # p = multiprocessing.Process(target=web_server, args=(new_socket,)) # p.start() # 2、协程实现并发服务 # p = gevent.spawn(web_server, new_socket) # p.start() # 3、多线程实现并发服务 t = threading.Thread(target=web_server, args=(new_socket,)) t.start() t.join() new_socket.close() tcp_socket.close() # 关闭监听套接字
if __name__ == '__main__':
main()
运行效果:
浏览器访问本地,会显示一个界面,而且可以开多个浏览器一起运行
2、单进程-单线程-非堵塞也可以实现并发服务器
"""利用单进程-单线程-非堵塞也可以实现web并发服务(即不用多线程,多进程,协程) 思路:1、设置套接字为非堵塞 2、在接收客户端处:因为是非堵塞,所以要捕捉异常,当有客户端进来,新客户端的套接字也要设置非堵塞 还需要判断接recv是否是有数据,没有数据说明客户端断开连接,关闭套接字 """ def main(): main_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) main_socket.bind(('127.0.0.1',7785)) main_socket.listen(128) main_socket.setblocking(False) socket_list = list() while True: time.sleep(1) try: new_socket,new_adress = main_socket.accept() except: print('没有客户端进来,请稍等.....') else: print('一个新的客户端进来了......') new_socket.setblocking(False) socket_list.append(new_socket) for client in socket_list: try: recv_data = client.recv(1024).decode('utf-8') except: print('客户端没有发送过来数据') else: print('无异常') if recv_data: print('客户端发来了消息') print(recv_data) data1 = recv_data.splitlines() res = re.match("[^/]+(/[^ ]*)", data1[0]) if res: file_name = res.group(1) print('--------------' + res.group(1)) if file_name == '/': file_name = '/index.html' try: data = open('./html' + file_name, 'rb') except: data_body = 'HTTP 404 NOT FOUND/1.1\r\n' data_body += '\r\n' data_body += '<h1>not found</h1>' client.send(data_body.encode('utf-8')) else: data_body = data.read() data.close() data_head = 'HTTP 200 OK/1.1\r\n' data_head += 'Content-Length:%d\r\n' % len(data_body) data_head += '\r\n' reponse = (data_head.encode('utf-8')+data_body) client.send(reponse) else: client.close() socket_list.remove(client) main_socket.close() if __name__ == '__main__': main()