2013-03-14 67 views
3

我有一個客戶端 - 服務器應用程序,其中每端通過TCP套接字與另一端進行通信。在由對等關閉的TCP套接字上進行寫入

我正確地建立了連接,然後在服務器崩潰之前,客戶端在套接字上寫入任何數據。
我看到的第一個write()嘗試(客戶端)是成功的,它返回實際寫入字節數,而下面的返回(如我所料)-1(接收SIGPIPE)和errno=EPIPE

即使套接字已關閉,爲什麼第一個write()成功?

編輯 有時也以下write()有正收益值,如一切順利。

回答

5

您對write()的返回值意味着什麼感到困惑。這並不意味着「同行得到了數據並承認了它」。相反,它的意思是,「我緩存了很多字節發送給對等方,他們現在是我的責任,所以你可以忘記它們(並且我沒有任何掛起的錯誤)」。即,如果TCP堆棧接受寫入並返回字節,這並不意味着它們已經寫入,只是排隊等待寫入。在堆棧放棄並向您返回錯誤之前,它需要一段時間,也就是在開始發送網絡通信之後30秒。在此期間,您可以撥打write()進行多次呼叫,這些呼叫已成功排隊發送數據。 (如果對等體已經消失,寫入錯誤將在30秒內返回,或者立即如果可以聯繫對等體並立即發送RST數據包以指示連接已死亡)。

3

這與TCP/IP的工作方式有關,可以粗略描述爲兩個大多數獨立的半連接。當您關閉服務器上的套接字時,客戶端會被告知它不會從C<-S半連接接收到更多數據,立即喚醒read(),但不會向C->S方向發送數據。它只會在嘗試發送一些數據後獲得重置連接的回覆。我建議TCP/IP Guide進一步的細節。

有時您可以兩次輸入write()的原因是,您的回寫速度比往返時間快,並且可以在回覆第一個回覆之前擠出第二個write()

0

我正在使用以下方法來檢測斷開連接的服務器狀態:

'在系統(「ping -c 1 -w 1 server」); 「命令被激活。 如果服務器啓動並剛剛落後,ping命令將在不到0.1秒的時間內返回。 否則(服務器關閉),ping命令將在1秒內返回。