web-dev-qa-db-fra.com

Détecter la connexion Internet en utilisant Java

Duplicata possible:
Comment vérifier si une connexion Internet est présente dans java?

Je veux voir si quelqu'un a un moyen facile de détecter s'il existe une connexion Internet lors de l'utilisation de Java. L'application actuelle a utilisé la méthode "InternetGetConnectedState" dans WinInit DLL pour Windows, mais mon application doit être multiplateforme pour le fonctionnement mac et cette méthode ne fonctionnera pas. Je ne connais pas JNI à tous d'utiliser des DLL dans Java et c'est devenu rapidement frustrant.

Les seules façons auxquelles je pouvais penser étaient d'essayer d'ouvrir une connexion URL à un site Web et, si cela échoue, de retourner false. Mon autre chemin est ci-dessous, mais je ne savais pas si cela était généralement stable. Si je débranche mon câble réseau, j'obtiens une exception UnknownHostException lorsque j'essaie de créer InetAddress. Sinon, si le câble est connecté, j'obtiens un objet InetAddress valide. Je n'ai pas encore testé le code ci-dessous sur un mac.

Merci pour tous les exemples ou conseils que vous pouvez fournir.

MISE À JOUR: Le bloc de code final est en bas. J'ai décidé de suivre les conseils d'une requête HTTP (dans ce cas Google). C'est simple et envoie une demande au site pour que les données soient retournées. Si je ne peux obtenir aucun contenu de la connexion, il n'y a pas d'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;
        }

Bloc de code final:

//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;
        }
36
Ken

C'est une approche parfaitement raisonnable pour résoudre le problème. La mauvaise chose est que vous testez vraiment DNS plutôt que de tester l'ensemble du réseau, mais dans la pratique, vous pouvez souvent vous en sortir en les traitant comme équivalents.

L'autre chose à retenir est que vous devrez définir une propriété système pour désactiver la mise en cache DNS dans le runtime Java. Sinon, il peut continuer à signaler que le réseau est en fonction des données mises en cache (même s'il est en panne).

Une autre approche consisterait à ouvrir une requête HTTP vers une adresse réseau telle que celle-ci de temps en temps.

17
jsight

Je dois ajouter que bien que le bloc de code final donné ci-dessus soit bon, il a un défaut - il peut prendre beaucoup de temps pour contacter l'adresse spécifiée, mais l'adresse est toujours accessible.

Dans mon cas, lors du test avec une seule adresse, la méthode retournerait true, mais prendrait 10 secondes ou plus pour obtenir une réponse. Dans ce cas, le serveur était accessible, mais pas à des fins utiles car la connexion était si lente. Cela se produit car le délai d'expiration par défaut pour HttpURLConnection est , ou infini.

Pour cette raison, je vous recommande de vérifier le thread d'interface utilisateur et d'ajouter urlConnect.setConnectTimeout(1000);avant appelant urlConnect.getContent();

De cette façon, vous savez que l'adresse est accessible et que cela ne prendra pas 5 ans pour télécharger un fichier de 10k.

(Vous pouvez bien sûr vouloir modifier le délai d'expiration en fonction de vos besoins)

Je vous recommande également de ne pas vérifier une adresse générique (google.com, etc.) à moins que votre programme accède généralement à plusieurs domaines. Si vous accédez simplement à un ou deux, vérifiez ce domaine.

11
Joseph Earl

Notez qu'il pourrait retourner false si Java.Sun.com ne répond pas! Dans ce cas, vous devez vérifier un autre site pour en être certain.

3
user95947

Un problème avec la première solution est qu'InetAddress a un cache, donc, lorsque vous perdez la connexion pour les prochains appels, le nom est résolu via le cache Java. Avec l'approche de connexion URL que vous avez le problème que vous utilisez getContent qui devrait récupérer du HTML pour que vous ayez la consommation de données. Si les appels sont effectués très souvent, cela pourrait être un problème (plus encore si vous n'avez pas de forfait de données illimité sur l'appareil exécutant le logiciel).

Je pense que la meilleure solution serait de faire une connexion TCP au port 80 et de la fermer immédiatement après une connexion réussie. Cela se comporterait comme le code final mais aurait beaucoup moins de trafic.

2
andsegu

Je n'ai pas testé cela, mais je suggère de regarder Java.net.NetworkInterface.getNetworkInterfaces (). Cela renvoie une énumération de toutes les interfaces réseau sur la machine, ou null s'il n'y en a pas.

Je ne sais pas s'il est sûr de supposer qu'une réponse non nulle garantit une connexion réseau valide - selon vos besoins, vous pouvez ou non avoir besoin de filtrer les adresses de bouclage (ce que je pense que vous pourriez faire avec Java.net .NetworkInterface.getInetAddresses () sur chaque NetworkInterface retournée, puis en appelant InetAddress.isLoopbackAddress () sur chacun.)

2
jptsetme

La seule façon d'être CERTAIN que vous pouvez accéder à un service donné est de faire une demande fictive à ce service. Les pings peuvent être bloqués par des pare-feu. Certains serveurs peuvent être accessibles, d'autres non. Si vous avez besoin de parler à un webservice, ayez une page statique à renvoyer pour ces demandes.

N'oubliez pas non plus de demander à l'utilisateur avant d'essayer de tendre la main.

2

La question n'a pas vraiment de sens. Il n'existe pas de "connexion à Internet". Vous devez essayer de créer un. L'API Windows à laquelle vous faites référence ne vous indique que si votre modem est connecté ou non, et je l'ai vu en fait cause appels entrants, ce qui n'est pas exactement l'idée. Non pas que j'aie un accès commuté depuis environ 8 ans.

1
user207421