2009-07-16 15 views
35
mit

Mögliche Duplizieren:
How to check if internet connection is present in java?Internet-Verbindung erkennen Java

Ich möchte sehen, ob jemand eine einfache Möglichkeit des Erfassens hat, wenn es eine Internet-Verbindung ist bei der Verwendung von Java. Die aktuelle App verwendete die "InternetGetConnectedState" -Methode in der WinInit-DLL für Windows, aber meine App muss für den Mac-Betrieb plattformübergreifend sein und auf diese Weise nicht funktionieren. Ich kenne JNI überhaupt nicht, um DLLs in Java zu verwenden, und es wurde schnell frustrierend.

Ich konnte nur daran denken, eine URL-Verbindung zu einer Website zu öffnen, und wenn das fehlschlägt, gibt false zurück. Mein anderer Weg ist unten, aber ich wusste nicht, ob das im Allgemeinen stabil war. Wenn ich mein Netzwerkkabel abziehe, erhalte ich eine UnknownHostException, wenn ich versuche, die InetAddress zu erstellen. Ansonsten, wenn das Kabel angeschlossen ist, bekomme ich ein gültiges InetAddress-Objekt. Ich habe den untenstehenden Code noch nicht auf einem Mac getestet.

Vielen Dank für alle Beispiele oder Ratschläge, die Sie zur Verfügung stellen können.

UPDATE: Der letzte Codeblock befindet sich unten. Ich entschied mich, den Rat einer HTTP-Anfrage (in diesem Fall Google) zu nehmen. Es ist einfach und sendet eine Anfrage an die Website für Daten zurückgegeben werden. Wenn ich keinen Inhalt von der Verbindung bekomme, gibt es kein Internet.

public static boolean isInternetReachable() 
     { 
      try { 

       InetAddress address = InetAddress.getByName("java.sun.com"); 

       if(address == null) 
       { 
        return false; 
       } 

      } catch (UnknownHostException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       return false; 
      } 
      catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       return false; 
      } 
      return true; 
     } 

finaler Code Block:

//checks for connection to the internet through dummy request 
     public static boolean isInternetReachable() 
     { 
      try { 
       //make a URL to a known source 
       URL url = new URL("http://www.google.com"); 

       //open a connection to that source 
       HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection(); 

       //trying to retrieve data from the source. If there 
       //is no connection, this line will fail 
       Object objData = urlConnect.getContent(); 

      } catch (UnknownHostException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       return false; 
      } 
      catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       return false; 
      } 
      return true; 
     } 

Antwort

17

, die zur Lösung des Problems einen vollkommen sinnvollen Ansatz ist. Das Schlimme ist, dass Sie wirklich DNS testen, anstatt das gesamte Netzwerk zu testen, aber in der Praxis können Sie oft damit umgehen, dass Sie diese als gleichwertig behandeln.

Die andere Sache zu erinnern, ist, dass Sie eine System-Eigenschaft festlegen müssen, um DNS-Caching in der Java-Laufzeit zu deaktivieren. Andernfalls kann es weiterhin melden, dass das Netzwerk auf zwischengespeicherten Daten basiert (obwohl es ausgefallen ist).

Ein anderer Ansatz wäre, tatsächlich eine HTTP-Anfrage zu einer solchen Netzwerkadresse zu öffnen.

+0

Danke für den Kommentar. Es ist immer gut, Feedback und andere Ideen zu bekommen. Ich dachte an die URL-Verbindung oder an HttpURLConnection. Ich war mir nicht bewusst, dass dies nur DNS getestet, aber ich muss mit dieser Methode leben. –

+0

Siehe oben stehenden Codeblock und Aktualisierungshinweis. –

3

Beachten Sie, dass es false zurückgeben könnte, wenn java.sun.com nicht reagiert! In diesem Fall sollten Sie eine andere Website überprüfen, um sicherzugehen.

+0

Guter Punkt. Ich denke das ist, warum die .NET-Version dieser App die DLL für das Betriebssystem verwendet. Auf diese Weise wusste das Betriebssystem sofort, ob es eine Verbindung gab oder nicht, kein Pingen von Webseiten oder das Überprüfen von Steams. Es würde die Frage aufwerfen, wann die Grenze gezogen werden sollte. Nach einer Seite? Zwei? Genau, warum ich Eingang wollte. –

2

Ich habe das nicht getestet, aber ich schlage vor, java.net.NetworkInterface.getNetworkInterfaces() zu betrachten. Dies gibt eine Enumeration aller Netzwerkschnittstellen auf dem Computer zurück, oder Null, wenn keine vorhanden sind.

Ich bin nicht sicher, ob es sicher ist anzunehmen, dass eine Antwort ungleich Null eine gültige Netzwerkverbindung gewährleistet - abhängig von Ihren Anforderungen müssen Sie möglicherweise Loopback-Adressen herausfiltern (was Sie meiner Meinung nach tun könnten) mit java.net.NetworkInterface.getInetAddresses() auf jedem zurückgegebenen NetworkInterface, und dann Aufruf von InetAddress.isLoopbackAddress() auf jedem.)

2

Der einzige Weg, sicher zu sein, dass Sie einen bestimmten Dienst erreichen können, ist ein Dummy-Anfrage an diesen Dienst. Pings können durch Firewalls blockiert werden. Einige Server sind möglicherweise erreichbar, andere nicht. Wenn Sie mit einem Webservice sprechen müssen, müssen Sie eine statische Seite für diese Anfragen zurückgeben.

Denken Sie auch daran, den Benutzer zu fragen, bevor Sie versuchen, zu erreichen.

+0

Der einzige Weg, auf den Sie sich verlassen können, ist die * real * Anfrage. Eine Pseudoanforderung an die reale Anforderung könnte fehlschlagen, wenn die reale Anforderung erfolgreich wäre, oder * umgekehrt. Sie können die Zukunft nicht vorhersagen. – EJP

2

Die Frage hat eigentlich keine Bedeutung. Es gibt keine "Verbindung zum Internet". Sie müssen versuchen, erstellen eins. Die Windows-API verweist nur darauf, ob Ihr Modem angewählt ist oder nicht, und ich habe es tatsächlich gesehen Ursache Einwahl, die nicht genau die Idee ist. Nicht, dass ich in den letzten 8 Jahren oder so eine Einwahl hatte.

+0

Dies liefert keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag. –

+1

@IanLim Die Antwort hier ist "Sie müssen versuchen, eine zu erstellen", und es stimmt mit den meisten anderen überein. – EJP

2

Ein Problem mit der ersten Lösung ist, dass InetAddress einen Cache hat. Wenn Sie also die Verbindung für die nächsten Aufrufe verlieren, wird der Name über den Java-Cache aufgelöst. Mit dem URL-Verbindungsansatz haben Sie das Problem, dass Sie getContent verwenden, das HTML holen sollte, damit Sie Datenverbrauch haben. Wenn die Aufrufe sehr oft ausgeführt werden, könnte das ein Problem sein (mehr, wenn Sie auf dem Gerät, auf dem die Software ausgeführt wird, keinen unbegrenzten Datentarif haben).

Ich denke, die beste Lösung wäre, eine TCP-Verbindung zum 80 Port zu machen und sie sofort nach einer erfolgreichen Verbindung zu schließen. Das würde sich wie der endgültige Code verhalten, hätte aber viel weniger Verkehr.

11

Ich muss hinzufügen, dass, obwohl der letzte Codeblock oben ist gut, es hat einen Fehler - es ist möglich, dass es sehr lange dauern, um die angegebene Adresse zu kontaktieren, aber die Adresse ist immer noch erreichbar.

In meiner Instanz würde die Methode beim Testen mit einer Adresse true zurückgeben, aber 10 Sekunden oder länger dauern, um eine Antwort zu erhalten. In diesem Fall war der Server erreichbar, aber für keine nützlichen Zwecke, da die Verbindung so langsam war. Dies tritt auf, weil das Standardzeitlimit für HttpURLConnection oder unendlich ist.

Aus diesem Grund würde ich empfehlen Sie den UI-Thread das Abhaken tun, und urlConnect.setConnectTimeout(1000);vorurlConnect.getContent();

diese Weise können Sie die Adresse kennen Aufruf hinzufügen erreichbar ist, und dass es 5 Jahre nicht nehmen um eine 10k-Datei herunterzuladen.

(Sie könnten natürlich wollen die die Timeout-Zeit zu ändern, um Ihre Bedürfnisse anzupassen)

Auch würde ich empfehlen, nicht eine allgemeine Adressprüfung (google.com etc.), es sei denn Ihr Programm im Allgemeinen greift auf mehr als ein paar Domänen. Wenn Sie nur auf ein oder zwei zugreifen, überprüfen Sie diese Domäne.

+0

Dies ist eine sehr wichtige Tatsache zu berücksichtigen. Ich musste mit diesem Problem konfrontiert werden, während ich die App in der virtuellen Maschine testete. Und es dauerte ewig, um Verbindung zu bekommen. Verbindungszeitüberschreitung ist in diesem Fall dann wichtig. – Indigo

+0

in Erwägung ziehen, Timeout hinzuzufügen, könnte es manchmal wichtig sein. – Vishrant

Verwandte Themen