簡體   English   中英

如何在Java中立即識別出斷開的套接字連接?

[英]How to identify a broken socket connection in Java immediately?

我有一個典型的Java客戶端和服務器。 客戶端向服務器發送一些請求並等待響應。 客戶端從包含的輸入流中讀取100個字節的數據到一個字節數組中。 它等待在指定的超時時間(例如3秒)內讀取100字節的完整響應。 這里的問題是在寫入響應時/之前確定服務器是否發生故障或崩潰。 基本上,我們需要確定套接字是否因為某些原因而斷開或者對等端斷開連接。 有沒有辦法識別這個?

如何在Java中立即識別出斷開的套接字連接?

您無法使用Java或任何其他語言立即檢測到它。 TCP / IP不知道,所以Java無法知道。 檢測TCP連接損壞的唯一可靠方法是寫入並捕獲IOExceptions,它們不會立即發生。

標識連接的最佳方法是關閉連接。 即,您希望在給定的時間內得到響應,並標記該響應是否未按預期進行。

如果你有一個正常的斷開連接(例如,另一端調用close()),一旦緩沖區被耗盡,連接上的讀數就會通知你。

但是,如果出現其他類型的故障,則在操作系統超時(例如3分鍾后)之前可能不會收到通知,實際上,您可能希望保持連接。 例如,如果您將網絡電纜拉出10秒鍾並將其重新插入,則無需失敗。

編輯:我認為在自動處理連接/服務“失敗”方面過於激進是一個好主意。 基於對真實原因的調查,通常可以通過對系統的計划修復來更好地處理。 例如,增加帶寬,冗余連接,更快的服務器,代碼修復。

如果連接異常中斷,讀取時會收到IOException ; 這通常發生得非常快,但無法保證時間 - 所有這些都取決於操作系統,網絡硬件等。如果遠程端正常關閉套接字,您將讀取-1作為下一個字節。

假設其他一切正常,如果遠程對等方 - TCP服務器 - 被殺死,那么TCP客戶端通常會收到TCP RST(重置),並且您將在客戶端應用程序中獲得IOException

但是,除了正在被殺死的進程之外,還有許多其他問題可能會出錯。 基本上兩個進程之間的網絡路徑上的任何東西:電纜被拉扯,路由器死亡,防火牆死亡等等。所有這些都不會立即被檢測到。

由於上述原因,一般規則是 - 正如EJP的答案所指出的那樣 - 斷開的連接只能通過寫入來檢測 這就是為什么始終建議TCP客戶端和TCP服務器定期交換某種類型的心跳消息。 有不同的方法來做到這一點。 我最喜歡TCP客戶端的方法 - 在沒有從TCP服務器接收數據的情況下 - 向服務器發送心跳消息並期望在特定時間段內回復。 這樣,只有在真正需要時才會發送心跳消息。

一種次優的方法 - 如果你不能實現真正的心跳 - 就是總是以超時讀取。 在套接字上設置超時 ,然后捕獲java.net.SocketTimeoutException 這將使您知道在x毫秒內沒有在套接字上收到任何數據。

應該提到的是,有一種情況是您不必使用心跳,也不必使用套接字超時:如果TCP客戶端和TCP服務器通過環回接口進行通信,則斷開的連接將始終傳播到TCP客戶端應用程序和TCP服務器應用程序。 這是因為,在這種情況下,兩個進程之間實際上沒有網絡基礎結構。 因此,如果您的現有應用程序在其TCP通信方面沒有很好的設計(即它沒有實現某種形式的心跳或至少讀取超時),那么作為最后的手段,您可以“修復”通過將兩個應用程序移動到同一主機上並讓它們通過環回接口進行通信來解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM