网络I/O模型
一、阻塞型
阻塞型I/O模型一次只能处理一个连接,每次遇到都会阻塞,等待操作系统将数据返回,处理效率不高。阻塞型I/O模型示例:
#普通的socket服务端程序都是I/O阻塞的 import socket phone=socket.socket() phone.bind(('127.0.0.1',8081)) phone.listen() while True: conn,addr=phone.accept() while True: try: data=conn.recv(1024) conn.send(data.upper()) except Exception: break conn.close() phone.close()
二、非阻塞型I/O模型
非阻塞型I/O模型再遇到I/O阻塞时不会一直等待操作系统将数据返回,而是在操作系统准备的过程中执行其他任务,之后在去跟操作系统确认数据是否准备完毕,不建议使用占用CPU太高。非阻塞I/O模型代码示例:
from socket import * s=socket() s.bind(('127.0.0.1',8080)) s.listen() s.setblocking(False) #设置I/O不阻塞,没有数据返回就抛出BlockingIOError异常 conn_l=[] del_l=[] while True: try: conn,addr=s.accept() conn_l.append(conn) except BlockingIOError: #捕捉到BlockingIOError异常就执行其他任务 for conn in conn_l: try: data=conn.recv(1024) conn.send(data.upper()) except BlockingIOError: pass except ConnectionResetError: del_l.append(conn) for conn in del_l: conn.close() conn_l.remove(conn) del_l.clear()
三、I/O多路复用
I/O多路复用就是同时监听多个连接的I/O状态,然后把就绪的连接返回出来做数据处理,它相比于阻塞型I/O模型的优势在于能够同时处理多个连接,不适合处理单个连接。同时epoll模型在I/O监听的处理效率上比select效率高,因为它是采用连接主动通知的方式告诉监听程序哪个连接已经就绪,而select则是一个个去检测,但是epoll只支持Linux。I/O多路复用的示例:
from socket import * import select s=socket() s.bind(('127.0.0.1',8080)) s.listen() s.setblocking(False) s_l=[s,] while True: r_l,_,_=select.select(s_l,[],[]) #select模块第一个列表是可以开始接收数据的socket对象集合,第二个列表是可以开始发送数据的socket对象集合,第三个列表是连接出错的socket对象;select模块可以监测任何有fileno方法的对象 for obj in r_l: if obj==s: conn,addr=obj.accept() s_l.append(conn) else: data=obj.recv(1024) obj.send(data.upper())

浙公网安备 33010602011771号