Day38 python基础--并发编程基础-IO模型

一,IO模型,这里的指的是linux环境下networl IO

  1.blocking IO  (阻塞IO)

  2.nonblocking IO (非阻塞IO)

  3.IO multiplexing  (IO多路复用)

  4.asynchronous IO  (异步IO)

  5.signal driven IO  (信号驱动IO) 在实际中并不常用,所以主要介绍其余四种IO模型

  IO发生时涉及的对象和步骤:对于一个network IO (以read为例,即类似recv操作),他会涉及到两个系统对象,一个是调用这个IO的process(or thread),另一个就是系统内核(kernel)。当一个read操作发生时,该操作会经历两个阶段:

  1.等待数据准备(waiting for the data to be ready)

  2.将数据从内核拷贝到进程中(copying the data from the kernel to the process)

  这些IO模型的区别就是在这个两个阶段上各有不同的情况

  

  网络IO的阻塞与非阻塞

    socket:

      1.用socket一定会用到accept,recv,recvfrom这些方法

      2.正常情况下 accept,recv,recvfrom 都是阻塞的

      3.如果setblocking(False),整个程序就变成一个非阻塞的程序

二,阻塞IO模型

  阻塞IO的recv

    wait for data阶段--阻塞

    copy data 阶段--阻塞

  缺点:一旦阻塞就不能做其他事情了

三,非阻塞IO模型

  缺点:对cpu造成很大的负担

  非阻塞IO模型:

    1.没有并发编程的机制

    2.同步的程序

    3.非阻塞的特点

    4.程序不会在某一个连接的recv或者sk的accept上进行阻塞,可以有更多的时间来做信息的收发工作

    5.但是一直在执行while True,会大量的占用了cpu导致了资源的浪费,对cpu负担较大

#非阻塞IO
import time
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.setblocking(False)   # 设置当前的socket server为一个非阻塞IO模型
sk.listen()
conn_l = []
del_l = []
while True:
    try:
        conn,addr = sk.accept()
        conn_l.append(conn)   # [conn1,conn2]
    except BlockingIOError:
        for conn in conn_l:   # [conn1,conn2]
            try:
                conn.send(b'hello')
                print(conn.recv(1024))
            except (NameError,BlockingIOError):   #由于recv非阻塞,没有收到信息就会报错blockingioerror,nameerror处理conn的报错
          pass except ConnectionResetError: #当客户端中断连接时,异常处理 conn.close() del_l.append(conn) for del_conn in del_l: conn_l.remove(del_conn) del_l.clear()

四,IO多路复用

  1.select:window/mac/linux均支持

    底层是操作系统的轮询

    有监听对象个数的限制

    随着监听对象的个数增加,效率降低

  2.poll:mac/linux均支持

    底层是操作系统的轮询

    有监听对象个数的限制,但是比select能监听的个数多

    随着监听对象的个数增加,效率降低

  3.epoll:mac/linux均支持

    给每一个要监听的对象都绑定了一个回调函数

    不再受到个数的增加,效率降低的影响

  IO复用的应用:

    socketserver:IO多路复用+threading线程

  拓展:selectors模块

    帮助你在不同的操作系统上进行IO多路复用机制的自动筛选

import select  #  模块
import socket
# 用来操作操作系统中的select(IO多路复用)机制
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.setblocking(False)
sk.listen()

r_lst = [sk,]
print(sk)
while True:
    r_l,_,_ = select.select(r_lst,[],[])  # r_lst = [sk,conn1,conn2,conn3]
    for item in r_l:
        if item is sk:
            conn, addr = sk.accept()
            r_lst.append(conn)
        else:
            try:
                print(item.recv(1024))
                item.send(b'hello')
            except ConnectionResetError:
                item.close()
                r_lst.remove(item)

 五,异步IO:

  1.通知操作系统,程序正在等待消息

  2.操作系统监听到消息后,copy数据到内核后,直接推送到程序内存中

  3.同时程序也处于异步执行状态

  

  

原文地址:https://www.cnblogs.com/lianyeah/p/9715100.html