2013-05-29 118 views
2

我正在編寫一個客戶機 - 服務器程序。服務器爲select()readfd1等待readfd1的準備就緒狀態被讀取。如果準備就緒,服務器正在收集數據並打印。一切都很好,但一段時間後,套接字recv()失敗,errno設置爲ETIMEDOUT。現在我想重寫我的程序來挫敗這些錯誤狀況。所以我經歷了Richard Stevens的「Unix Network Programming」,其中規定了select()的4個條件來解鎖。以下是引起我注意的兩個條件:套接字錯誤意味着套接字是否關閉

A. client sent FIN, here return value of `recv()` will be `0` 
B. some socket error, here return value of `recv()` will be `-1`. 

我的問題是,套接字錯誤是否會關閉連接?如果是這樣,那麼爲什麼上述兩個條件是分開的。如果沒有,插座上的下一個recv()工作?

回答

3

如果recv()返回0,另一端已主動正常關閉連接。

如果recv()返回-1,則連接上可能有(可能)錯誤,並且不再可用。

這意味着您可以分辨關閉連接的同伴與連接上發生的錯誤之間的差異。在這兩種情況下都需要做的事情是在你的socket的末尾使用close()

有2個點,但考慮:

recv()返回-1的情況下,你應該檢查錯誤號,因爲它可能不表示真正的錯誤。 errno可以是EAGAIN/EWOULDBLOCK如果您已將套接字置於非阻塞模式,或者如果系統調用被信號中斷,則它可能是EINTR。所有其他errno值意味着連接中斷,並且您應該關閉它。

TCP可以在半雙工模式下運行。如果對方僅關閉了連接的寫入端,則recv()會在您的末尾返回0。常見的做法是將連接視爲已完成,並關閉連接的結束,但可以繼續寫入連接,另一端可以繼續讀取連接。是否僅關閉TCP連接的讀取或寫入結束由shutdown()函數控制。

1

套接字錯誤並不一定意味着連接已關閉,請考慮例如發生了什麼情況,如果以某種方式切斷了您與對等體之間的網絡電纜,則通常會出現ETIMEDOUT錯誤。大多數錯誤是不可恢復的,所以關閉錯誤連接的結束幾乎總是可取的。

select可以解除阻塞的兩種狀態之間的差異是因爲另一端以很好的方式(第一種情況)關閉了它們的連接,或者存在一些實際的錯誤(第二種情況)。