阻塞:遇到IO操作就会发生阻塞,程序一旦遇到阻塞操作停在原地,立刻释放cpu资源
非阻塞:没有遇到IO操作,或者通过某种手段让程序即便是遇到IO操作也不会停在原地,执行其他操作,力求尽可能多的占用cpu
阻塞,非阻塞(就绪,运行)
同步与异步指的是提交任务的两种方式
同步调用:提交任务后,停在原地等待,直到任务运行完毕后,拿到任务结果,才执行下一行代码
异步调用:提交任务后,不在原地等待,直接执行下一行代码
IO
本地IO和网络IO
网络IO的两种状态,wait_data,copy_data
copy_data 应用程序将要发送的信息copy给操作系统
当操作系统copy好信息后,copy_data就结束了
应用程序的send操作就完成了
IO模型:
1.阻塞IO
应用程序发起recvfrom ,发起系统调用,然后等待操作系统接收到信息后将信息从操作系统缓存copy到应用程序
wait_data,copy_data都在等待
2.非阻塞IO
设置s.setblocking = False
应用程序发起recvfrom,系统调用,系统回信号,没有数据
然后应用程序执行其他任务,
应用程序向操作系统不停发起recvfrom,直到等到数据
cpu占用率过高
非阻塞IO的关键在于捕捉,BlockingIOError
from socket import *s = socket()s.bind(("127.0.0.1",8888))s.listen(5)s.setblocking(False)c_li = []msg_li = []while True: try: client,addr = s.accept() c_li.append(client) except BlockingIOError:#在所有阻塞的地方捕捉异常 for c in c_li[:]: try: msg = c.recv(1024) if not msg: c_li.remove(c) continue msg_li.append((c,msg)) except BlockingIOError: pass except ConnectionResetError: c_li.remove(c) for c_d in msg_li[:]: try: c_d[0].send(c_d[1]) msg_li.remove(c_d) except ConnectionResetError: c_li.remove(c_d[0]) msg_li.remove(c_d)
3.多路复用IO
import selectfrom socket import *s = socket()s.bind(("127.0.0.1",8888))s.listen(5)rlist = [s,]wlist = []msg_li = {}while True: r_li,w_li,_ = select.select(rlist,wlist,[]) for c in r_li: if c == s: client,addr = c.accept() rlist.append(client) continue try: msg = c.recv(1024) if not msg: rlist.remove(c) continue wlist.append(c) msg_li[c] = msg except ConnectionResetError: rlist.remove(c) for client in w_li: try: client.send(msg_li[client]) wlist.remove(client) except ConnectionResetError: wlist.remove(client)
通过select模块检测IO,不会过高占用CPU
4.异步IO
联系客服