阻塞和非阻塞socket總結

非阻塞socket設置方法:

fcntl(socket_fd, F_SETFL,  fcntl (socket_fd, F_GETFL,0) | O_NONBLOCK);

非阻塞模式下錯誤處理:

EAGAIN和EWOULDBLOCK(windows下)錯誤,這表明你在非阻塞模式下調用了阻塞操作,在該操作沒有完成就返回這個錯誤,關於此錯誤一種說法是此錯誤表示目前無端口可用,另一種說法說的是發送緩衝區已滿,遇到這兩種錯誤不能當作錯誤處理,一種處理方法是採用延時處理稍後發送/接收,另一種是在類似poll/select/epoll中繼續監聽下次繼續發送/接收,很顯然第一種方法不可取,影響性能。當發送大量數據時,可以通過緩存保存數據。如果出現EINTR錯誤,錯誤描述爲Interrupted system call,操作也應該繼續。如果recv的返回值爲0,那表明連接已經斷開,我們的接收操作也應該結束。

發送數據:

阻塞與非阻塞send返回值沒有區分,

<0,出錯,

=0,連接關閉,

>0,發送數據大小。

非阻塞模式下返回值 <0時並且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情況下認爲連接是正常的, 繼續發送。

阻塞模式下send會阻塞着發送數據,非阻塞模式下如果暫時無法發送數據會返回,不會阻塞着 send,因此需要循環發送。

接收數據:

阻塞與非阻塞recv返回值沒有區分,

<0,出錯,

=0,連接關閉,

>0,接收到數據大小,

非阻塞模式下返回 值 <0時並且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情況 下認爲連接是正常的,繼續接收。

阻塞模式下recv會阻塞着接收數據,非阻塞模式下如果沒有數據會返回,不會阻塞着讀,因此需要 循環讀取。

連接:

TCP socket 被設爲非阻塞後調用 connect ,connect 函數如果沒有馬上成功,會立即返回EINPROCESS(如果被中斷返回EINTR) ,但 TCP 的 3 次握手還在繼續進行。之後可以用 select /epoll檢查連接是否建立成功(但不能再次調用connect,這樣會返回錯誤EADDRINUSE)。

非阻塞 connect 有3 種用途:

(1). 在3 次握手的同時做一些其他的處理。

(2). 可以同時建立多個連接。

(3). 在利用 select/epoll 等待的時候,可以給 select/epoll 設定一個時間,從而可以縮短 connect 的超時時間。

使用非阻塞 connect 需要注意的問題是:

(1). 很可能 調用 connect 時會立即建立連接(比如,客戶端和服務端在同一臺機子上),必須處理這種情況。

(2). Posix 定義了兩條與 select/epoll 和 非阻塞 connect 相關的規定:

連接成功建立時,socket 描述字變爲可寫。(連接建立時,寫緩衝區空閒,所以可寫)

連接建立失敗時,socket 描述字既可讀又可寫。 (由於有未決的錯誤,從而可讀又可寫)

另外對於無連接的socket類型(SOCK_DGRAM),客戶端也可以調用connect進行連接,此連接實際上並不建立類似SOCK_STREAM的連接,而僅僅是在本地保存了對端的地址,這樣後續的讀寫操作可以默認以連接的對端爲操作對象。



作者:明明就_c565
鏈接:https://www.jianshu.com/p/286fc6f992b6
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章