UNIX網路程式設計 非阻塞式IO總結

2021-07-03 13:05:30 字數 1337 閱讀 2329

這兩周又一次忙於專案,不過好在我的考試基本都結束了,所以抓緊速度把unp這本書全部過了一遍,程式全部編譯執行過,重點本分自己手敲了部分**。現在回來補上自己部落格拉下的債了。

這一部分在unp書上的做法實際上時非常複雜的,為了實現非阻塞的io讀寫,創立了兩個緩衝區, 

1. 用來讀取來自客戶端上的輸入,並輸出給伺服器的 

to緩衝區, 

2. 用來儲存來自伺服器返回到客戶端上的輸入,並輸出給終端的 

fr緩衝區 

他們都使用兩個指標來維護,乙個指向已儲存的第乙個位元組,另乙個指向可用的第乙個位元組。然後使用select輪詢 是否有檔案描述符可讀或者可寫,然後使用非阻塞的讀寫操作。

總結使用非阻塞的connect使用一下步奏: 

1. 使用fcntl將套接字設定為非阻塞fcntl(sockfd, f_setfl, flags|o_nonblock);

2. 發起非阻塞的connect,如果返回的錯誤是einprogress則忽略該錯誤。(注意如果connect返回值為0時,那麼代表連線已經立刻建立成功了,可以直接使用)。 

3. 呼叫select或者poll或者epoll,來等待套接字變成可讀或者可寫。 

4. 返回後,如果返回值為0則超時,不為0則先呼叫getsockopt去獲取待處理錯誤 

if(getsockopt(sockfd, sol_socket, so_error, &error, &len)<0)

返回值小於0或者error被設定為不為0的數值,則是有錯誤。返回值為0那麼就代表建立連線成功(建立連線成功或者出錯對於select來說都是即可讀又可寫的)。

設定非阻塞的accept只需要將監聽套接字設定為非阻塞即可,並且由於要將監聽套接字設定為非阻塞式的,所以一般為了防止輪詢,會使用select或者epoll監視監聽套接字,有連線的時候才呼叫accept,那麼這時候問題來了,為什麼可讀之後還需要使用非阻塞的accept呢? 

原因如下: 

1. 客戶在成功連線,完成三次握手之後,設定so_linger選項並且關閉套接字,這時會傳送乙個rst給伺服器 

2. 伺服器在select返回之後,由於處理繁忙,未能立刻呼叫accept,等呼叫的時候,伺服器已經接受到rst,並且這個已完成的連線被清除出佇列了,那麼accept呼叫將會阻塞,直到下乙個連線到達。

因此使用阻塞式accept就是為了防止這樣的情況發生,因此在使用非阻塞式accept的時候需要忽略以下錯誤:

非阻塞式的讀寫方式盡量少用,使用epoll監聽描述符能解決讀寫阻塞的問題,非阻塞的connect與accept都可以使用,能提高效率,需要配合select或epoll使用,同時注意要忽略掉必要的錯誤。

Linux網路程式設計(九) 非阻塞式I O

套接字的預設狀態是阻塞的。當發出乙個不能立即完成的套接字呼叫時,其程序將被投入到睡眠,等待相應操作完成。可能阻塞的套接字呼叫可分為以下四類 1 輸入操作,包括read readv recv recvfrom和recvmsg等5個函式 對於非阻塞的套接字,如果輸入操作不能被滿足,相應的呼叫立即返回乙個...

阻塞式 非阻塞式IO

知識點 非阻塞式io 的兩種設定方法 1 函式fcntl 設定 o nonblock 選項 int flag fcntl sockfd,f getfl,0 檢查檔案標誌位 fcntl sockfd,f setfl,flag o nonblock 設定檔案標誌位 2 函式ioctl 設定fionbio...

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

linux下,可以通過設定socket使其變為non blocking。當對乙個non blocking socket執行讀操作時,流程是這個樣子 從圖中可以看出,當使用者程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者程序,而是立刻返回乙個error。從使...