2014-01-26 33 views

回答

18

在通常情況下,客戶端通過close()關閉套接字並且TCP關閉握手已經成功完成,(3或channelClosed())事件channelInactive()將被觸發。

但是,在一個不尋常的情況下,如客戶端機器由於停電或拔下LAN電纜而脫機時,可能需要很長時間直到您發現連接實際上斷開。爲了檢測這種情況,您必須定期發送一些消息給客戶,並期望在一定的時間內收到響應。這就像一個ping - 你應該在你的協議中定義一個週期性的ping和pong消息,這實際上只是檢查連接的健康狀況。

或者,您可以啓用SO_KEEPALIVE,但此選項的存活時間間隔通常取決於操作系統,我不推薦使用它。

爲了幫助用戶比較容易地實現這種行爲,Netty提供了ReadTimeoutHandler。配置您的管道,以便ReadTimeoutHandler在沒有入站流量一段時間時引發異常,並在您的exceptionCaught()處理程序方法中關閉異常時的連接。如果您是應該定期發送ping消息的一方,請使用計時器(或IdleStateHandler)發送該消息。

0

這取決於你使用netty的ontop的協議。如果您將其設計爲支持類似ping的消息,則可以簡單地發送這些消息。除此之外,netty只是TCP的一個很薄的包裝。

另請參閱this SO post其中描述了isOpen()和相關。但是這並不能解決保持活着的問題。

+0

在該鏈接的答案大多是不正確。 SO中有更好的答案。 – EJP

+0

@EJP你有鏈接嗎?如果你可以建議編輯,我會高興地接受! –

+0

我的理解是,tcp內置了keep-alive。是不是可以利用它? –

0

如果您正在編寫一個服務器,並且netty是您的客戶端,那麼您的服務器可以通過調用select()或等效項來檢測何時該插口可讀,然後調用recv()來檢測到斷開連接。如果recv()返回0,那麼套接字將被客戶端正常關閉。如果recv()返回-1然後檢查errno或等同於實際的錯誤(除了少數例外,大多數錯誤應被視爲非正常斷開連接)。關於意外斷開的事情是,他們可能需要較長的時間OS進行檢測,所以你必須要麼啓用TCP保持活動,或要求客戶將數據發送到服務器定期。如果在一段時間內沒有收到客戶端的任何信息,那麼就假設客戶端已經關閉並關閉了連接。如果客戶想要,它可以重新連接。

+0

我認爲你誤解了這個問題。他似乎在服務器上使用Netty。 – EJP

0

如果您從對等關閉的連接中讀取數據,則會根據API獲取某種類型的流結束指示。如果你寫這樣的連接,你會得到一個IOException:'連接重置'。 TCP不提供任何其他檢測關閉連接的方式。

默認情況下,TCP保持活動狀態(a)默認爲關閉狀態,(b)啓用時默認每兩小時運行一次。這可能不是你想要的。如果您使用它並且在檢測到連接斷開之後您讀取或寫入,則會出現上述重置錯誤,

+0

在Windows 2000及更高版本中,可以使用'WSAIoctl(SIO_KEEPALIVE_VALS)',按照每個連接的基礎,可編程地設置TCP保持活動的期望時間間隔。 –