2013-07-14 41 views
1
public static void main(String args[]){ 

    byte[] message = ... 
    Socket socket = ... 
    DataOutputStream dOut = new DataOutputStream(socket.getOutputStream()); 

    dOut.write(message); //#1 

    dOut.close(); 
    socket.close(); 
} 

我們假設第1行將數據放入緩衝區,等待刷新到遠程機器。之後,流和套接字被關閉。Java TCP重新傳輸超時

我們假設在發送過程中,網絡中發生了一些未知的問題,我們的操作系統會重新發送緩衝區中的數據包,直到TCP重新傳輸超時。

我想知道如何在Java程序中捕獲此異常?因爲上面的代碼已經將數據發送到緩衝區並可能關閉了流和套接字(可能會退出Java主體),所以將所有其他作業(TCP相關,重新傳輸)留給操作系統。

我的問題是,TCP重新傳輸(我們假設包丟失)甚至Java程序退出?捕獲重傳超時錯誤的最佳方法是什麼?

+0

沒有'Java TCP重傳超時'或者'Java TCP'這樣的東西。只有*平臺的* TCP堆棧及其行爲。 – EJP

+0

嗨@EJP,我知道dOut.write只會在TCP發送緩衝區已滿時被阻塞。我們假設,dOut.write因爲緩衝區已滿而被阻塞,並且網絡在發送數據時有一些問題,所以TCP繼續重新傳輸數據。在這種情況下,TCP超過最大重傳時間後,dOut.write會拋出異常嗎?感謝幫助。 – GMsoF

回答

2

即使在程序退出後,TCP仍將繼續嘗試乾淨地關閉連接。通常建議應用程序自行執行關閉。基本上,您執行以下步驟序列:

  1. Shutdown the TCP connection in the send direction觸發正常關閉序列。如果協議禁止對方發送任何數據,您也可以在接收方向關閉連接,但是,如果您這樣做而另一方發送了任何數據,則可能會導致另一端檢測到異常關閉它發送的數據將會丟失。

  2. 繼續從連接讀取,直到從另一端檢測到乾淨或異常關閉爲止。如果一切順利,只要您完成接收對方發送的任何數據,您就會檢測到乾淨的關機。

  3. 關閉句柄或刪除對象/對連接的引用。實際的TCP連接已經關閉。

+0

嗨,我不完全理解第一行「即使在程序退出後,TCP仍將繼續嘗試徹底關閉連接」。是說,操作系統會繼續發送(直到遠程機器接收數據或超時),甚至Java程序已經退出? – GMsoF

+0

@GMsoF:這取決於實施。它可能是操作系統。它可能是一個獨立的TCP棧,不屬於操作系統的一部分。它可能是JVM。但這是最常見的做法。爲了安全起見,應用程序應該管理關閉以確保它獲得所需的行爲。 –

+0

JVM退出後,它不能是JVM。 – EJP