阻塞IO模型(blocking IO)
因为通信的时候,数据是先复制到系统,再通过网线发送的,所以,recv在等待接受数据的时候,会先跟内核/操作系统要数据。进而出现两个等待过程,一个是系统等待对方发送数据、一个是应用程序等待系统的数据拷贝过来。
非阻塞IO是通过不断轮询,直到操作系统拿到数据,把数据拷贝给应用程序,但是,在操作系统将数据拷贝给用户进程的过程还是会被阻塞的(block)。
注意:需要关闭阻塞,server.setblocking(False)
缺点:这种方式会提高cpu占用率,同时,如果出现轮询第二个的时候,第一个人连接成功,这时候,要等待轮询结束后,重新开始轮询才可以轮到第一个人通话,这样会增加等待时间。
优点:能够在等待的过程做其他事情。
多路复用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)
原理:有点类似回调机制,用户进程发起read操作后,就不再等待,而是继续执行其他任务,等read操作全部完成后,会发送一个信号告诉用户进程read操作完成。在这个过程中不会对用户进程产生任何阻塞(IO)