Python之阻塞IO模型与非阻塞IO模型
Python之阻塞IO模型与非阻塞IO模型
IO模型
1 阻塞IO:
全程阻塞
2 非阻塞IO:
发送多次系统调用:
优点:wait for data时无阻塞
缺点:1 系统调用太多 2 数据不是实时接受的
两个阶段:wait for data:非阻塞
copy data :阻塞
3 IO多路复用(监听多个连接)
sock::sock <socket.socket fd=224,
family=AddressFamily.AF_INET,
type=SocketKind.SOCK_STREAM,
proto=0, laddr=('127.0.0.1', 8800)>
对于文件描述符(套接字对象):
1 是一个非零整数,不会变
2 收发数据的时候,对于接收端而言,数据先到内核空间,
然后copy到用户空间,同时,内核空间数据清除。
特点:
1 全程(wait for data,copy)阻塞
2 能监听多个文件描述符
实现并发
IO多路复用的实现机制:
win:Select
Linux:Select and Poll or Epoll (有epoll用epoll,没有则Select)
Select的缺点:
1、每次调用Select 都要将所有的fd(文件描述符)拷贝到内核空间。从而导致效率下降。
2、遍历所有的fd,是否有数据访问。浪费时间(最重要的问题)
3、最大连接数(1024)
poll:
1、最大连接数没有限制。这是和Select最大的区别。
epoll:
内部通过三个函数实现的。
1、第一个函数:创建一个epoll句柄。方便将fd以一次性的拷到内核去。but,只需要拷贝一次。
2、第二个函数:回调函数,在某一个函数或动作完成后会触发的函数。为所有的fd绑定一个回调函数。
一旦有数据访问,就会触发该回调函数,回调函数将fd放到列表中。
3、第三个函数:判断列表是否为空。
没有最大链接数。
4 异步IO
全程无阻塞
5 驱动信号
总结:
同步: 阻塞IO 非阻塞IO io多路复用
异步: 异步IO
Selectors模块:
1 import selectors # 基于select模块实现的IO多路复用,建议大家使用 2 3 import socket 4 5 sock=socket.socket() 6 sock.bind(("127.0.0.1",8800)) 7 8 sock.listen(5) 9 10 sock.setblocking(False) 11 12 sel=selectors.DefaultSelector() #根据具体平台选择最佳IO多路机制,比如在linux,选择epoll 13 14 def read(conn,mask): 15 16 try: 17 data=conn.recv(1024) 18 print(data.decode("UTF8")) 19 data2=input(">>>") 20 conn.send(data2.encode("utf8")) 21 except Exception: 22 sel.unregister(conn) 23 24 def accept(sock,mask): 25 26 conn, addr = sock.accept() 27 print("conn",conn) 28 sel.register(conn,selectors.EVENT_READ,read) 29 30 sel.register(sock,selectors.EVENT_READ,accept) # 注册事件 31 32 while 1: 33 34 print("wating...") 35 events=sel.select() # 监听 [(key1,mask1),(key2,mask2)] 36 for key,mask in events: 37 38 # print(key.fileobj) # conn 39 # print(key.data) # read 40 func=key.data 41 obj=key.fileobj 42 43 func(obj,mask) # 1 accept(sock,mask) # 2 read(conn,mask)