2014-01-26 6 views

Antwort

18

In einem üblichen Fall, wo ein Client den Socket über close() schließt und der TCP-Handshake geschlossen wurde erfolgreich beendet, wird ein channelInactive() (oder channelClosed() in 3) Ereignis ausgelöst.

In einem ungewöhnlichen Fall, in dem ein Client-Computer aufgrund eines Stromausfalls oder eines nicht angeschlossenen LAN-Kabels offline geht, kann es jedoch sehr lange dauern, bis Sie feststellen, dass die Verbindung tatsächlich unterbrochen wurde. Um diese Situation zu erkennen, müssen Sie regelmäßig eine Nachricht an den Client senden und erwarten, dass die Antwort innerhalb einer bestimmten Zeit erfolgt. Es ist wie ein Ping - Sie sollten in Ihrem Protokoll eine periodische Ping- und Pong-Nachricht definieren, die praktisch nur den Zustand der Verbindung überprüft.

Alternativ können Sie SO_KEEPALIVE aktivieren, aber das Keepalive-Intervall dieser Option ist normalerweise vom Betriebssystem abhängig und ich würde es nicht empfehlen.

Um einem Benutzer zu helfen, diese Art von Verhalten relativ einfach zu implementieren, bietet Netty ReadTimeoutHandler. Konfigurieren Sie Ihre Pipeline so, dass eine Ausnahme auslöst, wenn für eine bestimmte Zeit kein eingehender Datenverkehr vorhanden ist, und schließen Sie die Verbindung für die Ausnahme in Ihrer Handlermethode exceptionCaught(). Wenn Sie die Partei sind, die eine periodische Ping-Nachricht senden soll, verwenden Sie einen Timer (oder IdleStateHandler), um es zu senden.

0

Es hängt von Ihrem Protokoll ab, dass Sie ontop von netty verwenden. Wenn Sie es so entwerfen, dass es pingähnliche Nachrichten unterstützt, können Sie diese Nachrichten einfach senden. Abgesehen davon ist netty nur ein ziemlich dünner Wrapper um TCP.

Siehe auch this SO post, die isOpen() und verwandte beschreibt. Dies löst jedoch das Keep-Alive-Problem nicht.

+0

Die Antworten in diesem Link sind meistens falsch. Es gibt viel bessere Antworten in SO. – EJP

+0

@EJP Haben Sie einen Link? Wenn Sie eine Bearbeitung vorschlagen könnten, werde ich das gerne annehmen! –

+0

Mein Verständnis ist, dass TCP Keep-Alive eingebaut hat. Ist es nicht möglich, dies zu nutzen? –

0

Wenn Sie einen Server schreiben und netty Ihr Client ist, kann Ihr Server eine Verbindung durch Aufrufen von select() oder gleichwertig erkennen, um festzustellen, wann der Socket lesbar ist, und dann recv() anrufen. Wenn recv() 0 zurückgibt, wurde der Socket ordnungsgemäß vom Client geschlossen. Wenn recv() -1 zurückgibt, überprüfen Sie errno oder einen gleichwertigen Wert für den tatsächlichen Fehler (mit einigen Ausnahmen sollten die meisten Fehler als ungeplante Trennung behandelt werden). Das Problem bei unerwarteten Verbindungsabbrüchen besteht darin, dass das Erkennen des Betriebssystems lange dauern kann. Sie müssten entweder TCP-Keep-Alives aktivieren oder den Client dazu zwingen, regelmäßig Daten an den Server zu senden. Wenn für eine gewisse Zeit nichts vom Client empfangen wird, nehmen Sie einfach an, dass der Client verschwunden ist und schließen Sie das Ende der Verbindung. Wenn der Client das möchte, kann er sich wieder verbinden.

+0

Ich denke, Sie haben die Frage falsch gelesen. Er scheint Netty im Server zu benutzen. – EJP

0

Wenn Sie von einer Verbindung lesen, die vom Peer geschlossen wurde, erhalten Sie je nach API eine End-of-Stream-Meldung. Wenn Sie auf eine solche Verbindung schreiben, erhalten Sie eine IOException: 'Verbindung zurückgesetzt'. TCP bietet keine andere Möglichkeit, eine geschlossene Verbindung zu erkennen.

TCP keep-alive (a) ist standardmäßig deaktiviert und (b) wird standardmäßig nur alle zwei Stunden aktiviert, wenn es aktiviert ist. Das ist wahrscheinlich nicht das, was du willst. Wenn Sie es verwenden und Sie lesen oder schreiben, nachdem es festgestellt hat, dass die Verbindung unterbrochen ist, erhalten Sie den Fehler zurücksetzen,

+0

Unter Windows 2000 und höher können Sie das gewünschte Intervall des TCP Keep-Alive pro Verbindung mit 'WSAIoctl (SIO_KEEPALIVE_VALS)' programmierbar einstellen. –