IO多路复用:
导入包: import select
select: 支持平台:win/linux/unix
r,w,x = select(rlist,wlist,xlist,[timeout])
功能: 监控IO事件,阻塞等待IO事件发生
rlist: 列表,read list, 监控要等待处理的IO事件
wlist: 列表,存放希望主动处理的IO;如send
xlist: 列表,存放如果发生异常,需要我们处理的;open
timeout: 数字, 超时检测;可省略;默认一直阻塞
三个列表只要有任意一个IO事件准备就绪,就返回
返回值是列表
r: rlist中准备就绪的IO列表
w: wlist中准备就绪的IO列表
x:xlist中准备就绪的IO列表
注意:
1, 在处理IO过程中,不影响发生死循环(某个IO单独占有服务器)
2, IO多路复用是单进程程序,是一个并发程序
3, IO多路复用有较高的IO执行效率
poll: unix/linux
1,创建poll对象
p = select.poll()
2, 加入关注的IO
p.register(s)
p.unregister(s) 从关注列表中移除
poll的IO事件:
POLLIN: 相当于rlist;
POLLOUT: 类似wlist
POLLHUP: 断开连接
POLLERR:xlist
POLLPRI:紧急处理
3, 使用poll函数监控
events = p.poll()
POLLVAL: 无效数据
s & POLLIN
4, 处理发生的IO事件
epoll: linux/unix
用法通POLL
注意:
1,效率比poll和select稍微高些
2,支持边缘触发, select和poll只支持水平触发
多路复用代码:
from socket import *
from select import *
import sys
import traceback
#IO多路复用
sockfd = socket()
sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
sockfd.bind(('0.0.0.0',8888))
sockfd.listen(5)
rlist = [sockfd]
wlist = []
xlist = []
while True:
print('Waiting for IO')
rs,ws,xs = select(rlist,wlist,xlist,3)
#read list, 监控要等待处理的IO事件
for r in rs:
#套接字准备就绪
if r is sockfd:
connfd, addr = r.accept()
print("Connect from ", addr)
#将新的套接字加入到关注列表
rlist.append(connfd)
else:
try:
data = r.recv(1024)
if not data:
#如果断开,从rlist中移除该套接字
rlist.remove(r)
r.close()
else:
print("Msg Received from {}\n{}".format(r.getpeername(),data.decode()))
wlist.append(r)
except Exception:
print(traceback.print_exc())
xlist.append(r)
#存放希望主动处理的IO
for w in ws:
w.send("人道纪元".encode())
wlist.remove(w)
#xlist 存放如果发生异常,需要我们处理的事件
for x in xs:
x.close()
sys.exit(2)