一、用非阻塞IO解决阻塞IO模型
import socket sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() sk.setblocking(False) lst = [] del_lst = [] while 1: try: conn,address = sk.accept() lst.append(conn) except BlockingIOError: for conn in lst: try: dat = conn.recv(1024).decode('utf-8') if not dat: del_lst.append(conn) print('客户端正常关闭') conn.close() else: print(dat) conn.send(dat.upper().encode('utf-8')) except ConnectionResetError : continue except BlockingIOError: pass if del_lst: for i in del_lst: lst.remove(i) del_lst.clear()
import socket sk = socket.socket() sk.connect(('127.0.0.1', 8080)) while 1: word = input('>>>') if word == 'q': break sk.send(word.encode('utf-8')) info = sk.recv(1024).decode('utf-8') print(info) sk.close()
二、基于select的IO多路模型
select 和 poll ,epoll
select 和 poll 有一个共同机制:都采用轮询的方式去访问内核,问数据有没有准备好。
select 有一个最大的监听事件的限制,32位机限制是1024,64位机限制是2048。
poll 没有,理论上pool可以开启无限大
epool 采用的是回调机制,解决了select 和 poll 的缺点
二、用select解决IO阻塞
代码:
import socket import select sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() rlist = [sk] while 1: r, w, x = select.select(rlist, [], []) if r: for i in r: if i == sk: conn,address = i.accept() rlist.append(conn) else: try: dat = i.recv(1024).decode('utf-8') if not dat: print('客户端正常关闭') rlist.remove(i) i.close() else: print(dat) i.send(dat.upper().encode('utf-8')) except ConnectionResetError: continue
import socket sk = socket.socket() sk.connect(('127.0.0.1', 8080)) while 1: word = input('>>>') if word == 'q': break sk.send(word.encode('utf-8')) info = sk.recv(1024).decode('utf-8') print(info) sk.close()