2010-12-30 14 views
2

Ich baue eine Client-Server-Anwendung, wo ich einen Keepalive-Mechanismus implementieren muss, um festzustellen, ob der Client abgestürzt ist oder nicht. Ich habe getrennte Threads auf Client- und Server-Seite. der Client-Thread sendet ein "Ping" dann schläft für 3 Sekunden, während der Server liest die BufferedInputStream und überprüft, ob Ping empfangen wird, wenn ja, macht der Ping-Zähler gleich Null, sonst erhöht es den Zähler um +1, der Server-Thread dann schläft für 3 Sekunden, wenn der Ping-Zähler 3 erreicht, deklariert er den Client als tot.Implementieren von Keepalives mit Java

Das Problem ist, dass, wenn der Server den Eingabestream liest, ein blockierender Aufruf, und es blockiert, bis der nächste Ping empfangen wird, unabhängig davon, wie verzögert es ist, so dass der Server nie einen verpassten Ping erkennt.

Vorschläge, damit ich den aktuellen Wert des Streams lesen kann und nicht blockiert, wenn der eingehende Stream nichts enthält.

Danke,

+0

Können Sie bitte erklären "Server erkennt nie einen verpassten Ping"? –

+0

Sagen Sie zum Beispiel, dass der Client Keep-Alives alle 3 Sekunden sendet und der Server alle 3 Sekunden auch nach Keep-Alives sucht. Nun sagen Sie, der Client sendet keine Keep-Alive für 10 Sekunden, dann, wenn der Server nach dem Keep-Alive sucht, wird es nichts lesen, weil der Client nichts gesendet hat, so dass der Aufruf zum Lesen von Stream blockiert wird, bis es erhält das nächste Keepalive 10 Sekunden später, an dem der Server gerne erklärt, dass er ein Keepalive erhalten hat. So wird es niemals einen verlorenen Keep-Alive entdecken. – comatose

Antwort

5

Java 1.4 die Idee der non-blocking I eingeführt/O, durch das java.nio Paket vertreten. Das ist wahrscheinlich das, was du brauchst.

Siehe this tutorial for how to use non-blocking I/O.

Auch, wenn dies keine Hausaufgaben oder eine Lernübung ist, dann empfehle ich die Verwendung eines robuster Protokoll-Framework wie Apache Mina oder JBoss Netty, anstatt diese Sachen von Grund auf neu aufzubauen. Sehen Sie this comparison zwischen ihnen, und warum Sie sie verwenden möchten.

0

Sie können einen separaten Überwachungs-Thread verwenden, der alle blockierenden Verbindungen überwacht. Wenn eine Verbindung etwas empfängt, kann sie einen Zähler zurücksetzen. (Ich würde jedes Paket so gut wie einen Herzschlag behandeln) Ihr Überwachungs-Thread kann diesen Zähler jedes Mal erhöhen, wenn er ausgeführt wird und wenn er ein Limit erreicht (d. H. Weil er nicht auf Null zurückgesetzt wurde), können Sie die Verbindung schließen. Du brauchst nur einen solchen Thread. Der Thread, der die Verbindung blockiert, die Sie gerade geschlossen haben, löst eine IOException aus und weckt den Thread.

Auf der anderen Seite kann ein Heartbeat ausgelöst werden, wenn ein Paket für eine bestimmte Zeit nicht gesendet wurde. Dies bedeutet, dass eine besetzte Verbindung keine Heartbeats sendet, sollte es nicht müssen.