2010-07-07 17 views
5

在TCP套接字編程中,如果recv()返回0,則表示另一方關閉其連接。但是,AFAIK,TCP RFC沒有要求TCP的有效載荷大於0.因此,理論上,TCP堆棧可以接收有效載荷爲0的消息。如果接收到有效負載大小爲0的TCP數據包,則recv()返回什麼值

所以,基本上我的問題是recv()如果返回收到大小爲0的有效載荷數據包?如果它返回0,那麼我們如何區分它與關閉的連接指示。

回答

11

有效載荷大小爲0的TCP段無處不在 - 它們幾乎出現在每個真實世界的TCP流中。只要有一方希望承認收到另一方的數據,但沒有自己發送的數據,就會發送它們。 (這些通常被稱爲「ACK數據包」,但「ACK數據包」只是恰好不包含數據的常規段)。

由於這些包不包含任何數據,以便提供給用戶的應用程序,他們不會造成recv()返回 - recv()將繼續阻止,直到一些實際的數據到達。如果recv()返回0,則表明另一端已關閉其連接側,並且不會再發送更多數據。

請記住,TCP是面向流的:有而不是調用單個recv()返回的數據與單個TCP段中的數據之間的1對1映射。一個recv()調用可能會返回一個與多個TCP段重疊的數據塊,並且單個TCP段中的數據可能會在多個recv()調用中返回。使用BSD套接字API的應用程序不可見TCP段之間的邊界。如果你想要這樣的邊界,你需要在TCP流中使用應用層協議來實現自己,或者使用像UDP這樣的面向數據報的協議。

+0

+1用於提及ACK。 – 2010-07-08 10:51:12

+0

ACK數據包將設置一個ACK標誌。 – AlastairG 2010-12-22 13:56:08

+1

@AlastairG:對,但是除了初始SYN或連接重置之外的每個數據包都設置了ACK位。 – caf 2010-12-22 21:36:06

3

對,根據POSIX,如果recv返回0,則該連接被對等體正確關閉。

如果有人已經成功地發送TCP數據包以零大小的有效載荷,則OS 不必返回任何數據被阻止在該插座上recv系統調用的進程。

請記住,TCP有效載荷形成一個連續的流,可能由操作系統隨機分割,而不是在單個系統調用期間必須返回的數據報序列。

相關問題