1. 程式人生 > >並發編程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路復用io

並發編程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路復用io

post app decode pos win 循環 效率 網絡io als

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 break 12 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拿走了cpu 24 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:continue
10     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                     continue
29                 wlist.append((conn,data.upper()))
30             except BlockingIOError:
31                 continue
32             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                 pass
46 
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:continue
10     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                     continue
30                 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:continue
10     client.send(msg.encode(utf-8))
11     data=client.recv(1024)
12     print(data.decode(utf-8))
13 
14 client.close()


並發編程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路復用io