#
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
IO多路复用
操作系统提供给你的
对于你的程序来说 : 是一个代理
帮助你监听所有的通信对象,是否有数据来到操作系统中
一旦有 就通知你
你再根据通知来接收相应的数据
你不需要一直循环着问每一个对象是否有信息来,而是阻塞等待,任意一个对象有信息来,我就接收
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
io多路复用有好几种机制 : select poll epoll 多个io对象,多个conn,sk 一个conn占着一条网络连接的路 多个conn占着多条路 多个conn复用同一个线程的操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from socket import * import select s=socket(AF_INET,SOCK_STREAM) #允许端口重用 s.bind(('127.0.0.1',8081)) s.listen(5) s.setblocking(False) #设置socket的接口为非阻塞 read_l=[s,] while True: r_l,w_l,x_l=select.select(read_l,[],[]) #监听对象的读事件 print(r_l,read_l) for ready_obj in r_l: # if ready_obj == s: #sk conn,addr=ready_obj.accept() #此时的ready_obj等于s read_l.append(conn) #链接 else: try: data=ready_obj.recv(1024) #此时的ready_obj等于conn if not data: #主动断开链接 ready_obj.close() #关掉链接 read_l.remove(ready_obj) #删除这个conn continue ready_obj.send(data.upper()) #信息不为空 大写处理 except ConnectionResetError: #操作系统差异报警 ready_obj.close() #关闭连接 read_l.remove(ready_obj) #删除
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
vvvv
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
vvv
# 异步IO 就像快递直接放你座位上
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
vvv
# selectors 模块
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#服务端 from socket import * import selectors sel=selectors.DefaultSelector() def accept(server_fileobj,mask): conn,addr=server_fileobj.accept() sel.register(conn,selectors.EVENT_READ,read) def read(conn,mask): try: data=conn.recv(1024) if not data: print('closing',conn) sel.unregister(conn) conn.close() return conn.send(data.upper()+b'_SB') except Exception: print('closing', conn) sel.unregister(conn) conn.close() server_fileobj=socket(AF_INET,SOCK_STREAM) server_fileobj.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) server_fileobj.bind(('127.0.0.1',8088)) server_fileobj.listen(5) server_fileobj.setblocking(False) #设置socket的接口为非阻塞 sel.register(server_fileobj,selectors.EVENT_READ,accept) #相当于网select的读列表里append了一个文件句柄server_fileobj,并且绑定了一个回调函数accept while True: events=sel.select() #检测所有的fileobj,是否有完成wait data的 for sel_obj,mask in events: callback=sel_obj.data #callback=accpet callback(sel_obj.fileobj,mask) #accpet(server_fileobj,1) #客户端 from socket import * c=socket(AF_INET,SOCK_STREAM) c.connect(('127.0.0.1',8088)) while True: msg=input('>>: ') if not msg:continue c.send(msg.encode('utf-8')) data=c.recv(1024) print(data.decode('utf-8'))
socketserver
selectors模块 + threading模块实现的