1.io模型 提交任务得方式: 同步:提交完任务,等结果,执行下一个任务 异步:提交完,接着执行,异步 + 回调 异步不等结果,提交完任务,任务执行完后,会自动触发回调函数 同步不等于阻塞: 阻塞:遇到io,自己不处理,os会抢走cpu ,解决办法:监测到io,gevent切换到其他任务,类似欺骗os 非阻塞:cpu 运行
IO分类: 1.阻塞IO blocking IO 2.非阻塞IO nonblocking IO 3.IO多路复用 IO multiplexing 4.信号驱动IO signal driven IO 用得比较少 5.异步IO asynchronous IO
遇到IO: 卡 网络IO: 原地阻塞 1.server端什么样得操作属于IO行为 # accept recv send 阻塞操作 accept recv 明显得等 send 不会明显等,但是一种io行为 2.为什么IO行为会让有在原地等待的效果 2.阻塞io server:
1 from socket import * 2 from threading import Thread 3 4 def communicate(conn): 5 while True: 6 try: 7 data = conn.recv(1024) 8 if not data: break 9 conn.send(data.upper())10 except ConnectionResetError:11 break12 13 conn.close()14 15 16 17 server = socket(AF_INET, SOCK_STREAM)18 server.bind(('127.0.0.1',8080))19 server.listen(5)20 21 while True:22 print('starting...')23 conn, addr = server.accept() # io 阻塞 os拿走了cpu24 print(addr)25 26 t=Thread(target=communicate,args=(conn,))27 t.start()28 29 server.close()
client:
1 from socket import * 2 3 client=socket(AF_INET,SOCK_STREAM) 4 client.connect(('127.0.0.1',8080)) 5 6 7 while True: 8 msg=input('>>: ').strip() 9 if not msg:continue10 client.send(msg.encode('utf-8'))11 data=client.recv(1024)12 print(data.decode('utf-8'))13 14 client.close()
3.非阻塞io: 自己监测io 遇到io 就切 并且把 单线程得效率提到最高 导致得问题: 1.当有数据来得时候,cpu 在做其他得事情,不会立即响应 2.服务端没有任何阻塞,说白了,就是死循环,cpu会一直运转,线程处于就绪状态,大量占用cpu ,做无用,这个线程会一直问cpu,有数据没,有数据没 不推荐使用 server:
1 from socket import * 2 3 server = socket(AF_INET, SOCK_STREAM) 4 server.bind(('127.0.0.1',8083)) 5 server.listen(5) 6 server.setblocking(False) # 默认True 阻塞 7 print('starting...') 8 9 10 rlist=[]11 wlist=[]12 while True:13 14 try: # 服务端不停得建链接15 conn, addr = server.accept()16 rlist.append(conn)17 print(rlist)18 except BlockingIOError: # 没阻塞19 # print('干其他的活')20 21 #收消息22 del_rlist = []23 for conn in rlist:24 try:25 data=conn.recv(1024)26 if not data:27 del_rlist.append(conn)28 continue29 wlist.append((conn,data.upper()))30 except BlockingIOError:31 continue32 except Exception:33 conn.close()34 del_rlist.append(conn)35 36 #发消息37 del_wlist=[]38 for item in wlist:39 try:40 conn=item[0]41 data=item[1]42 conn.send(data) # send 在数据量 过大时 也会阻塞43 del_wlist.append(item)44 except BlockingIOError:45 pass46 47 for item in del_wlist:48 wlist.remove(item)49 50 for conn in del_rlist:51 rlist.remove(conn)52 53 54 server.close()
client:
1 from socket import * 2 3 client=socket(AF_INET,SOCK_STREAM) 4 client.connect(('127.0.0.1',8083)) 5 6 7 while True: 8 msg=input('>>: ').strip() 9 if not msg:continue10 client.send(msg.encode('utf-8'))11 data=client.recv(1024)12 print(data.decode('utf-8'))13 14 client.close()
4.多路复用io: wait copy 还多了select 中间有个中介存在,帮问os 有没有数据 但是如果中介 只有1个 效率不如 阻塞效率 但是如果中介监测多个套接字 ,性能高就是:同时监测多个套接字问os系统好了没 就比阻塞io效率高 监测套接字得io行为 服务端得套接字有几类:server conn select 阻塞io 效率高 比非阻塞io 效率也高 ,一直做无用 总结: 同时监测多个套接字 列表 循环 慢 假设列表数据多,循环 效率低 监测套接字好没好 从头到尾 循环1遍 select 列表循环 效率低 poll 可接收得列表数据多 效率也不高 epoll 效率最高得 异步操作 每个套接字身上绑定个回调函数,谁好了谁触发回调,(就不用去遍历了 效率低) epoll windows 不支持 linux 支持 selectors 模块 自动根据操作系统选择 poll epoll server:
1 from socket import * 2 import select 3 4 server = socket(AF_INET, SOCK_STREAM) 5 server.bind(('127.0.0.1',8083)) 6 server.listen(5) 7 server.setblocking(False) 8 print('starting...') 9 10 rlist=[server,]11 wlist=[]12 wdata={}13 14 while True:15 rl,wl,xl=select.select(rlist,wlist,[],0.5) # [] 异常列表 每隔0.5s 问一次16 print('rl',rl)17 print('wl',wl)18 19 for sock in rl:20 if sock == server:21 conn,addr=sock.accept()22 rlist.append(conn)23 else:24 try:25 data=sock.recv(1024)26 if not data:27 sock.close()28 rlist.remove(sock)29 continue30 wlist.append(sock)31 wdata[sock]=data.upper()32 except Exception:33 sock.close()34 rlist.remove(sock)35 36 for sock in wl:37 data=wdata[sock]38 sock.send(data)39 wlist.remove(sock)40 wdata.pop(sock)41 42 server.close()
client:
1 from socket import * 2 3 client=socket(AF_INET,SOCK_STREAM) 4 client.connect(('127.0.0.1',8083)) 5 6 7 while True: 8 msg=input('>>: ').strip() 9 if not msg:continue10 client.send(msg.encode('utf-8'))11 data=client.recv(1024)12 print(data.decode('utf-8'))13 14 client.close()