本文根據自身使用經驗,總結以下錯誤碼及其出現場景和一般處理流程.
網絡編程的一般性流程如下 :
客戶端 : socket -> connect -> write / read
服務端 : socket -> bind -> listen -> accept
還有因爲設置屬性帶來的其它改變,比如非阻塞和套接字選項.
EADDRINUSE : 如果你在同一個端口運行了無論是相同還是不同的程序,那麼bind就會出錯.即便是設置了SO_REUSEADDR,同一時刻也只允許同一個進程佔用指定端口,有一種極其特殊的情況,就是允許相同地址端口的完全重複綁定,但是這個特殊的情況需要傳輸協議支持,而且一般而言僅適用於UDP.(參考unp 7.5.11)
EINTR : 如果你並未對套接字設置非阻塞,那麼所有可能阻塞的函數都有可能遇到這個錯誤.比如connect,accept,read,write...等,面對這個錯誤,一般性的處理辦法是忽略掉它,繼續產生這個錯誤的操作.比如read一個套接字,如果遇到了這個錯誤,忽略掉,繼續read就行了.
if (errno == EINTR/* || errno == ECONNABORT*/)
{
continue;
}
else
{
return -1;
EAGAIN : 如果你得套接字是非阻塞的,你需要對read/write/recv/send...等函數判斷返回值,如果其失敗返回,並且errno是EAGAIN,這並不致命,你只要忽略它,繼續處理就行,這個錯誤只是告訴我們,當前這個套接字並沒有數據可讀或者並沒有空間裝得下將要發送的數據.
EPERM : 這個錯誤碼有點冷門了,我也是無意間遇到的.在編寫廣播程序的時候,如果採用了廣播地址,卻並未設置廣播屬性,就會出現這個errno
EPIPE : 這個錯誤應該是最複雜的一個錯誤了.我們首先需要了解的是在網絡編程中的一個特殊場景.
當一個套接字已經關閉了以後,如果我們繼續寫這個套接字,你並不會察覺有什麼異常,返回值告訴你,你寫成功了,但是如果通過wireshark抓包,你會發現,接收端回覆了一個RST,這個RST你根本就不知道.你唯一檢測它的辦法是讀一下這個套接字,此時會返回0,你才發現,原來連接已經斷開了.好吧,我假設我不管它,繼續寫,此時程序就會異常崩潰.是什麼導致了程序的崩潰呢,就是SIGPIPE,這個信號的默認行爲就是終止進程.
說回EPIPE,對於SIGPIPE,如果你沒有捕獲它,那麼程序也就退出了,也就談不上EPIPE了,所以,這個errno出現的前提一定是你設置了信號捕獲.那麼這個錯誤是否致命呢,看情況吧,反正連接也不在了,起碼拿到錯誤以後應該close掉本端的套接字.
以上...