阻塞IO模型(blocking IO)
因为通信的时候,数据是先复制到系统,再通过网线发送的,所以,recv在等待接受数据的时候,会先跟内核/操作系统要数据。进而出现两个等待过程,一个是系统等待对方发送数据、一个是应用程序等待系统的数据拷贝过来。
非阻塞IO(unLocking IO)
非阻塞IO是通过不断轮询,直到操作系统拿到数据,把数据拷贝给应用程序,但是,在操作系统将数据拷贝给用户进程的过程还是会被阻塞的(block)。
注意:需要关闭阻塞,server.setblocking(False)
缺点:这种方式会提高cpu占用率,同时,如果出现轮询第二个的时候,第一个人连接成功,这时候,要等待轮询结束后,重新开始轮询才可以轮到第一个人通话,这样会增加等待时间。
优点:能够在等待的过程做其他事情。
多路复用IO(multiplexing IO)
多路复用IO,基本原理就是把非阻塞IO的轮询操作给select/epoll来执行,当有数据到达的时候,就会通知用户进程。
用户进程调用select的时候,就会进入阻塞状态,直到监听的对象有数据过来,才会进行下一步将数据拷贝到进程。
注意:多路复用IO只有在处理多连接的时候才有优势。在处理单链接的优势不及阻塞IO。
#服务端
# -*-coding:utf-8 -*-
import socket
import select
server=socket.socket()
server.bind(('localhost',8080))
server.listen(5)
server.setblocking(False)
read_list=[server]
while True:
r_list,w_list,x_list=select.select(read_list,[],[])
print(r_list)
for li in r_list:
if li == server:
conn,addr=li.accept()
read_list.append(conn)
else:
data=li.recv(1024)
print(data)
li.send(data.upper())
#客户端
import socket
c=socket.socket()
c.connect(('localhost',8080))
while True:
c.send('hello world'.encode())
data=c.recv(1024)
print(data)
异步IO(asynchronous IO)
原理:有点类似回调机制,用户进程发起read操作后,就不再等待,而是继续执行其他任务,等read操作全部完成后,会发送一个信号告诉用户进程read操作完成。在这个过程中不会对用户进程产生任何阻塞(IO)