基于select的网络IO模型
#select 和 poll 和epoll的区别 ''' select和poll有一个共同的机制,都是采用轮训的方式去询问内核,有没有数据准备好了 select有一个最大监听事件的限制,32位机限制1024,,6位机限制2048 poll没有,理论上poll可以开启无限大,1G内存大概够你开10W个事件去监听 epoll是最好的,采用的是回调机制,解决了select和poll共同存在的问题 而且epoll理论上也可以开启无限多个监听事件 ''' # IO多路复用 ''' 阻塞IO 非阻塞IO 多路复用IO 异步IO python实现不了,但是有tornado框架,天生自带异步 ''' #服务器端 import socket import select sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() Conn_Del = [] #定义删除列表 rlist = [sk] #是用来让select帮忙监听的所有接口 # select:windows/linux是监听事件有没有数据到来 # poll: linux 也可以做select的工作 # epoll: linux 也可以做类似的工作 while 1: r,w,x = select.select(rlist,[],[]) #将rlist传给select,当rlist中哪个接口有反应,就返回给r这个列表 if r: for i in r: #循环遍历,看看有反应的接口是sk还是conn,因为如果是sk,后面会把conn也加到这个列表中 if i == sk: #如果是sk,表明有客户端的连接请求 conn,addr = i.accept() rlist.append(conn) #把新的客户端的连接,添加到rlist,继续让select帮忙监听 else: #如果是conn,代表客户端请求发送数据了(此时客户端已经连接上了) #下面的异常处理模型和非阻塞IO模型解决阻塞IO模型类似 try: msg = i.recv(1024).decode('utf-8') if not msg: #客户端正常关闭返回给服务器端一个空,即客户端执行了close() Conn_Del.append(i) i.close() else: #服务器端的逻辑层(以字符串大写的形式返回给客户端) print("接收到来自{}客户端的消息{}".format(i,msg)) i.send(msg.upper().encode('utf-8')) except ConnectionResetError: #客户端强制关闭 pass if Conn_Del: for conn in Conn_Del: rlist.remove(conn) Conn_Del.clear() sk.close() #客户端 import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while 1: msg_s = input('>>>') if not msg_s:continue if msg_s == 'q':break sk.send(msg_s.encode('utf-8')) print(sk.recv(1024).decode('utf-8')) sk.close()