IO模型
一:blocking IO(阻塞IO)
在linux中,默认情况下所有的socket都是blocking;

import socket sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.setsockopt(socket.SQL_SOCKET,socket.SO_REUSEADDR,1)#操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口 sock.bind(("127.0.0.1",9090))#绑定IP地址和端口 sock.listen(5)#设置挂起的链接数 while 1:#链接循环 conn,sddr=sock.accept() print("链接:",conn) while 1:#通信循环 try:#针对window系统里的链接断开所引发的异常 data=conn.recv(1024) if not data:continue#应对linux系统,当客户端断开链接,会不断的收空消息 print(data.decode("utf8")) except Exception:
blocking IO的特点就是在IO执行的两个阶段都被block;
二:non-blocking IO(非阻塞IO)

import socket sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.setsockopt(socket.SQL_SOCKET,socket.SO_REUSEADDR,1) sock.bind(("127.0.0.1",8080)) sock.listen(5) sock.setblocking(False)#默认是True while 1: try: conn,addr=sock.accept()#当内核没有返回数据的时候,就返回错误 print("conn:",conn) data=conn.recv(1024)#当内核没有返回数据的时候,就返回错误 print(str(data,"utf8")) except Exception as e: print(e)
总结:可以发送多次系统调用
优点:wait for data时无阻塞
缺点:<1>:系统调用太多<2>:数据不是实时接收
copy data:阻塞
三:multiplexing(IO多路复用)监听多个连接

import socket import select sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("127.0.0.1", 8080)) sock.listen(5) sock.setblocking(False) inputs = [ sock, ] while 1: r, w, e = select.select(inputs, [], [])#数据被拷贝到用户空间后,内核空间数据清除,然后继续监听内核空间,如有再有数据发过来,就发生了从0到有的变化 for obj in r: if obj == sock: conn, addr = obj.accept()#当select到消息后,再去取内核里的数据,如果不取,就一直在内核空间 inputs.append(conn) print("conn:",conn) else: try:#在window上,子链接断开触发的异常 data = obj.recv(1024)#当select到消息后,再去取内核里的数据,如果不取,就一直在内核空间 if not data:#linux上,子链接断开,会收到一个空 inputs.remove(obj)#删除子链接 continue print(data.decode("utf8")) send_data = input(">>> ") obj.send(send_data.encode("utf8")) except Exception: inputs.remove(obj)#删除子链接
注意1:select函数返回结果中如果有文件可读了,那么进程就可以通过调用接收accept()或recv()来让kernel将位于内核中准备到的数据copy到用户区;
2: select的优势在于可以处理多个连接,不适用于单个连接;
对于文件描述符(套接字对象):①是一个非零整数,不会改变;②收发数据的时候,对于接收端而言,数据先到内核空间,然后copy到用户空间,同时、内核空间数据清除;
特点:1:全程(wait for data,copy)阻塞
2:能监听多个文件描述符(链接),实现并发
四:Asynchronous I/O(异步IO)全程无阻塞
异步IO在请求完成时,通过将文件句柄设为有信号状态来通知应用程序,或者应用程序通过GetOverlappedResult察看IO请求是否完成,也可以通过一个事件对象来通知应用程序;
用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。
五:IO模型比较分析
阻塞IO:会一直阻塞住主进程直到操作完成
非阻塞IO:当内核准备数字中,会立即返回(如果没数据,就返回错误)
同步:在waitting for data 或者copy data的任意一个阶段有阻塞,就是同步的
异步:全程无阻塞
加深理解:
http://www.cnblogs.com/yuanchenqi/articles/6755717.html
http://www.cnblogs.com/Anker/p/3254269.html
https://www.zhihu.com/question/19732473?sort=created&page=2
IO在计算机中指Input/Output,也就是输入和输出;由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。

浙公网安备 33010602011771号