一,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.同时程序也处于异步执行状态