it-swarm.com.de

Java erkennt eine unterbrochene Verbindung

Wenn ich z. PuTTY und meine Verbindung geht verloren (oder wenn ich unter Windows einen manuellen Code ipconfig /release mache), sie reagiert direkt und benachrichtigt, dass meine Verbindung unterbrochen wurde.

Ich möchte ein Java-Programm erstellen, das meine Internetverbindung (zu einem zuverlässigen Server) überwacht, um das Datum und die Uhrzeit zu protokollieren, wenn mein Internet ausfällt.

Ich habe versucht, die Socket.isConnected()-Methode zu verwenden, aber das wird nur für immer "wahr" sein. Wie kann ich das in Java machen?

24
kresjer

Nun, der beste Weg, um festzustellen, ob Ihre Verbindung unterbrochen ist, besteht darin, zu versuchen, aus dem Socket zu lesen/schreiben. Wenn der Vorgang fehlschlägt, haben Sie Ihre Verbindung irgendwann verloren.

Alles, was Sie tun müssen, ist, das Lesen in bestimmten Abständen zu versuchen, und falls das Lesen fehlschlägt, versuchen Sie, die Verbindung erneut herzustellen.

Die wichtigsten Ereignisse für Sie sind, wenn ein Lesevorgang fehlschlägt - Sie haben die Verbindung verloren und wenn ein neuer Socket angeschlossen wird - Sie haben die Verbindung wieder hergestellt.

Auf diese Weise können Sie die Laufzeiten und Ausfallzeiten nachverfolgen.

20
jjnguy

Obwohl das TCP/IP-Protokoll "verbindungsorientiert" ist, werden normalerweise keine Daten über eine freie Verbindung gesendet. Sie können einen Socket für ein Jahr offen lassen, ohne dass ein einzelnes Bit vom IP-Stack darüber gesendet wird. Um zu bemerken, dass eine Verbindung unterbrochen wurde, müssen Sie einige Daten auf Anwendungsebene senden. (*) Sie können dies ausprobieren, indem Sie das Telefonkabel von Ihrem ADSL-Modem abziehen. Alle Verbindungen in Ihrem PC sollten aufrechterhalten bleiben, es sei denn, die Anwendungen verfügen über einen Keepalive-Mechanismus auf Anwendungsebene.

Die einzige Möglichkeit, eine verlorene Verbindung zu bemerken, besteht also darin, eine TCP - Verbindung zu einem Server zu öffnen und einige Daten davon zu lesen. Der einfachste Weg könnte sein, eine Verbindung zu einem FTP-Server herzustellen und gelegentlich eine kleine Datei (oder Verzeichnisliste) abzurufen. Ich habe noch nie einen generischen Server gesehen, der eigentlich für diesen Fall verwendet werden sollte, und Besitzer des FTP-Servers mögen dies möglicherweise nicht.

(*) Es gibt auch einen Mechanismus namens TCP keepalive. In vielen Betriebssystemen müssen Sie ihn jedoch für alle Anwendungen aktivieren. Wenn Sie einen Verbindungsverlust schnell feststellen möchten, ist dies nicht wirklich praktisch

11
tputkonen

Wenn der Client die Verbindung ordnungsgemäß getrennt hat, gibt read() -1 zurück, readLine() gibt null zurück, readXXX() für jedes andere X wirft EOFException. Die einzige zuverlässige Methode zum Erkennen einer verlorenen TCP -Verbindung besteht darin, darauf zu schreiben. Irgendwann wird also eine IOException 'connection reset' ausgelöst, es werden jedoch mindestens zwei Schreibvorgänge aufgrund der Pufferung ausgeführt.

7
user207421

Warum nicht die Methode isReachable() der Klasse Java.net.InetAddress verwenden?

Wie das funktioniert, ist für die Implementierung der JVM spezifisch, jedoch:

Bei einer typischen Implementierung werden ICMP-ECHO-ANFRAGEN verwendet, wenn das Privileg erhalten werden kann. Andernfalls wird versucht, eine TCP -Verbindung an Port 7 (Echo) des Zielhosts herzustellen.

Wenn Sie eine Verbindung ständig geöffnet halten möchten, um zu sehen, wann dies fehlschlägt, können Sie eine Verbindung zu einem Server herstellen, auf dem das ECHO-Protokoll selbst ausgeführt wird, anstatt dass isReachable() dies für Sie erledigt und Daten lesen und schreiben und warten muss Scheitern.

7
Dave Webb

Okay, damit habe ich es endlich geschafft

try
{
    Socket s = new Socket("stackoverflow.com",80);
    DataOutputStream os = new DataOutputStream(s.getOutputStream());
    DataInputStream is = new DataInputStream(s.getInputStream());
    while (true)
    {
        os.writeBytes("GET /index.html HTTP/1.0\n\n");
        is.available();
        Thread.sleep(1000);
    }
}
catch (IOException e)
{
    System.out.println("connection probably lost");
    e.printStackTrace();
}

Nicht so sauber, wie ich gehofft habe, aber es funktioniert nicht, wenn ich os.writeBytes () weglasse.

1
kresjer

Vielleicht möchten Sie das Socket Timeout-Intervall betrachten. Bei einem kurzen Timeout (I believe der Standardwert ist "Unendlich Timeout"), können Sie möglicherweise eine Ausnahme abfangen, wenn der Host nicht erreichbar ist.

1
poundifdef

Es ist wahrscheinlich einfacher, eine Verbindung zu Yahoo/Google oder einem anderen Ort herzustellen.

    URL yahoo = new URL("http://www.yahoo.com/");
    URLConnection yc = yahoo.openConnection();
    int dataLen = yc.getContentLength() ;

Neil

0
Neil Wightman

Sie könnten alle paar Sekunden einen Ping an eine Maschine senden, und das wäre ziemlich genau. Seien Sie vorsichtig, dass Sie es nicht DOS machen.

Eine andere Alternative wäre, einen kleinen Server auf einem Remote-Computer auszuführen und eine Verbindung zu ihm aufrechtzuerhalten.

0
Geo

Die isConnected()method in Socket.Java-Klasse ist etwas irreführend. Es sagt Ihnen nicht, ob der Socket gerade mit einem entfernten Host verbunden ist (wie wenn er nicht geschlossen ist). Stattdessen wird angezeigt, ob die Steckdose jemals mit einem entfernten Host verbunden wurde . Wenn der Socket überhaupt eine Verbindung zum Remote-Host herstellen konnte, gibt diese Methode true zurück, auch nachdem der Socket geschlossen wurde. Um festzustellen, ob ein Socket gerade geöffnet ist, müssen Sie prüfen, ob isConnected()true und isClosed()false zurückgibt. Zum Beispiel:

boolean connected = socket.isConnected() && !socket.isClosed();
0
Alboz