網路程式設計之IO模型 非阻塞IO

2022-07-04 03:15:13 字數 2287 閱讀 7091

linux下,可以通過設定socket使其變為non-blocking。當對乙個non-blocking socket執行讀操作時,流程是這個樣子:

從圖中可以看出,當使用者程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者程序,而是立刻返回乙個error。從使用者程序角度講 ,它發起乙個read操作後,並不需要等待,而是馬上就得到了乙個結果。使用者程序判斷結果是乙個error時,它就知道資料還沒有準備好,於是使用者就可以在本次到下次再發起read詢問的時間間隔內做其他事情,或者直接再次傳送read操作。一旦kernel中的資料準備好了,並且又再次收到了使用者程序的system call,那麼它馬上就將資料拷貝到了使用者記憶體(這一階段仍然是阻塞的),然後返回。

也就是說非阻塞的recvform系統呼叫呼叫之後,程序並沒有被阻塞,核心馬上返回給程序,如果資料還沒準備好,

此時會返回乙個error。程序在返回之後,可以幹點別的事情,然後再發起recvform系統呼叫。重複上面的過程,

迴圈往復的進行recvform系統呼叫。這個過程通常被稱之為輪詢。輪詢檢查核心資料,直到資料準備好,再拷貝資料到程序,進行資料處理。

需要注意,拷貝資料整個過程,程序仍然是屬於阻塞的狀態。

所以,在非阻塞式io中,使用者程序其實是需要不斷的主動詢問kernel資料準備好了沒有。

非阻塞io示例:

#服務端

from socket import *

server = socket(af_inet, sock_stream)

server.bind(('127.0.0.1',8099))

server.listen(5)

server.setblocking(false)

rlist=

wlist=

while true:

try:

conn, addr = server.accept()

print(rlist)

except blockingioerror:

del_rlist=

for sock in rlist:

try:

data=sock.recv(1024)

if not data:

except blockingioerror:

continue

except exception:

sock.close()

del_wlist=

for item in wlist:

try:

sock = item[0]

data = item[1]

sock.send(data)

except blockingioerror:

pass

for item in del_wlist:

wlist.remove(item)

for sock in del_rlist:

rlist.remove(sock)

server.close()

#客戶端

from socket import *

c=socket(af_inet,sock_stream)

c.connect(('127.0.0.1',8080))

while true:

msg=input('>>: ')

if not msg:continue

c.send(msg.encode('utf-8'))

data=c.recv(1024)

print(data.decode('utf-8'))

但是非阻塞io模型絕不被推薦。

我們不能否定其優點:能夠在等待任務完成的時間裡幹其他活了(包括提交其他任務,也就是 「後台」 可以有多個任務在「」同時「」執行)。

但是也難掩其缺點:

1、迴圈呼叫recv()將大幅度推高cpu佔用率;這也是我們在**中留一句time.sleep(2)的原因,否則在低配主機下極容易出現卡機情況。

2、任務完成的響應延遲增大了,因為每過一段時間才去輪詢一次read操作,而任務可能在兩次輪詢之間的任意時間完成。這會導致整體資料吞吐量的降低。

此外,在這個方案中recv()更多的是起到檢測「操作是否完成」的作用,實際作業系統提供了更為高效的檢測「操作是否完成「作用的介面,例如select()多路復用模式,可以一次檢測多個連線是否活躍。

非阻塞IO模型

include include include include include include in.h include include include include include using namespace std define maxsize 2048std queue socketqu...

網路程式設計 PHP 實現 「非阻塞IO模型「

如果看不明白,可以翻開我關於網路程式設計的其他 從簡單到複雜的實現 非阻塞io的使用使得可以在單個程序中管理多個連線 自定義流格式請檢視 注意 unix tcp是流 udp是資料報。addr tcp mode stream server bind stream server listen socke...

網路程式設計之IO模型 非同步IO

linux下的asynchronous io其實用得不多,從核心2.6版本才開始引入。先看一下它的流程 使用者程序發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到乙個asynchronous read之後,首先它會立刻返回,所以不會對使用者程序產生任何bl...