Python之阻塞IO模型与非阻塞IO模型

时间:2020-12-15 00:00:14

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模块:

Python之阻塞IO模型与非阻塞IO模型Python之阻塞IO模型与非阻塞IO模型
 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)
View Code

 

链接