一、概述
1、指的是针对网络的IO。
2、常见的会产生网络IO阻塞的状态:accept,recv(recvfrom)。
3、接收数据的两个阶段:操作系统等待对方数据传过来的wait_data(waiting for the data to be ready)和操作系统将数据从内核拷贝到进程的copy_data(copying the data from the kernel to the process)。
二、阻塞IO模型:对IO不做特殊处理。
import socket server = socket.socket() server.bind(('127.0.0.1', 3333)) server.listen(5) while 1: print('等待客户端连接...') conn, client_addr = server.accept() while 1: print('等待客户端发送数据...') try: recv_data = conn.recv(1024) if len(recv_data) == 0: break send_data = '收到:'.encode('utf-8') + recv_data conn.send(send_data) except ConnectionResetError: print('客户端已经断开') break conn.close()
三、非阻塞IO模型:通过不断询问操作系统实现的无阻塞,但是如此会长时间占用cpu使之空转。
import socket server = socket.socket() server.bind(('127.0.0.1', 3333)) server.listen(5) server.setblocking(False) # 如此声明,可以将所有网络阻塞变为异常 BlockingIOError r_list = [] # 初始化可用连接列表 del_list = [] # 初始化待清除列表 while 1: try: conn, client_addr = server.accept() r_list.append(conn) except BlockingIOError: print('跳过等待客户端连接') for conn in r_list: try: recv_data = conn.recv(1024) if len(recv_data) == 0: conn.close() # 关闭无用连接 del_list.append(conn) # 将无用连接加入待清除列表 continue send_data = '收到:'.encode('utf-8') + recv_data conn.send(send_data) except BlockingIOError: print('跳过等待客户端发送数据') continue except ConnectionResetError: print('客户端已断开') conn.close() # 关闭无用连接 del_list.append(conn) # 将无用连接加入待清除列表 for conn in del_list: r_list.remove(conn) # 从可用连接列表中清除无用连接 del_list.clear() # 初始化待清除列表
四、多路复用IO模型:通过导入select模块,将可能产生IO阻塞的对象交给操作系统的监管机制select,一个监管者可以同时监管多个对象,通过不断轮询这些对象来获悉这些对象是否脱离了IO阻塞,若脱离,则返回给程序执行。除了select机制,还有只能在linux系统上用的poll机制,poll机制能监管的对象数量更多,但是select和poll因为都是轮询的方式,所以都会产生较大的响应延迟,所以在linux系统上衍生了epoll机制,给每个监管对象绑定了回调机制,实现了即时响应,但是该机制不兼容windos系统。最终产生了selector模块,可以识别不同系统,选择对应的监管机制。
import socket import select server = socket.socket() server.bind(('127.0.0.1', 3333)) server.listen(5) server.setblocking(False) read_list = [server] # 把服务端对象加入读操作列表 while 1: select_obj = select.select(read_list, [], []) # 把读操作列表和另外两个空列表加入监管名录 r_list = select_obj[0] # 监管对象脱离阻塞才会返回到可操作列表 for obj in r_list: # 遍历可操作列表 if obj is server: # 是服务端对象的情况 print('只有当有客户端连接才会执行到本处') conn, client_addr = obj.accept() read_list.append(conn) else: # 是连接对象的情况 try: print('只有当客户端发来数据才会执行到本处') recv_data = obj.recv(1024) if len(recv_data) == 0: obj.close() # 关闭无效连接 read_list.remove(obj) # 将无效连接移除可操作列表 continue send_data = '收到:'.encode('utf-8') + recv_data obj.send(send_data) except ConnectionResetError: print('客户端已断开连接') obj.close() # 关闭无效连接 read_list.remove(obj) # 将无效连接移除可操作列表
五、异步IO模型:是IO模型发展至目前最优模型,避开了前面几代的诸多缺点,是目前效率最高的,广泛的引用于相关的模块与框架中。
1、模块:asyncio。
2、框架:sanic,tronado,twisted。