106 votes

Pourquoi InetAddress.isReachable renvoie-t-il false, alors que je peux envoyer un ping à l'adresse IP ?

InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));

Pourquoi est-ce que isReachable retourner false ? Je peux faire un ping sur l'IP.

0 votes

1 votes

C'est similaire. mais je n'ai pas trouvé d'indice pour résoudre le problème. donc je l'ai soulevé à nouveau ici. Merci pour votre rappel !

2 votes

J'essaierais d'augmenter le délai d'attente.

74voto

jayunit100 Points 6468

Le site "isReachable" n'a pas été digne d'être utilisée pour moi dans de nombreux cas. Vous pouvez faire défiler jusqu'en bas pour voir mon alternative pour simplement tester si vous êtes en ligne et capable de résoudre des hôtes externes (i.e. google.com) ... Ce qui semble généralement fonctionner sur les machines *NIX.

La question

Il y a beaucoup de discussions à ce sujet :

Partie 1 : Un exemple reproductible du problème

Notez que dans ce cas, il échoue.

       //also, this fails for an invalid address, like "www.sjdosgoogle.com1234sd" 
       InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
      for (InetAddress address : addresses) {
        if (address.isReachable(10000))
        {   
           System.out.println("Connected "+ address);
        }
        else
        {
           System.out.println("Failed "+address);
        }
      }
          //output:*Failed www.google.com/74.125.227.114*

Partie 2 : Une solution de contournement pirate

Comme alternative, vous pouvez faire ceci :

// in case of Linux change the 'n' to 'c'
    Process p1 = java.lang.Runtime.getRuntime().exec("ping -n 1 www.google.com");
    int returnVal = p1.waitFor();
    boolean reachable = (returnVal==0);

L'option -c de ping permettra à ping d'essayer d'atteindre le serveur une seule fois (par opposition au ping infini que nous avons l'habitude d'utiliser dans le terminal).

Cela donnera 0 si l'hôte est joignable . Sinon, vous obtiendrez "2" comme valeur de retour.

C'est beaucoup plus simple, mais cela dépend bien sûr de la plate-forme. Et il peut y avoir des problèmes de privilèges liés à l'utilisation de cette commande - mais je trouve qu'elle fonctionne sur mes machines.


VEUILLEZ noter que : 1) Cette solution n'est pas de qualité production. C'est un peu un hack. Si google est en panne, ou si votre internet est temporairement lent, ou peut-être même s'il y a quelque chose d'amusant dans vos privilèges/paramètres système, il pourrait retourner des faux négatifs (c'est-à-dire qu'il pourrait échouer même si l'adresse d'entrée est atteignable). 2) L'échec de isReachable est un problème en suspens. Encore une fois - il y a plusieurs ressources en ligne qui indiquent qu'il n'y a pas de manière "parfaite" de faire cela au moment de la rédaction de cet article, en raison de la manière dont la JVM essaie d'atteindre les hôtes - je suppose que c'est une tâche intrinsèquement spécifique à la plate-forme qui, bien que simple, n'a pas encore été suffisamment abstraite par la JVM.

0 votes

@jayunit100 car aucune de ces approches ne fonctionne, ou isReachable J'obtiens un échec et en utilisant ping j'obtiens icmp not permitted ? Savez-vous comment traiter ce problème ?

6 votes

@Yuvi Si vous utilisez Windows, les drapeaux sont différents. Au lieu de -c, vous voulez -n.

0 votes

WaitFor() prend 10 secondes pour revenir. Existe-t-il un moyen de mentionner le délai d'attente dans Java 7 ?

7voto

CleanX Points 161

Si vous voulez seulement vérifier s'il est connecté à l'Internet, utilisez cette méthode, qui renvoie vrai si l'Internet est connecté. Il est préférable d'utiliser l'adresse du site auquel vous essayez de vous connecter à travers le programme.

     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 (Exception e) {              
            e.printStackTrace();
            return false;
        }

        return true;
    }

3 votes

Inutile si le serveur n'a pas de serveur web, ce n'est pas du tout une condition spécifiée dans la question.

4voto

Zitrax Points 3443

Je le mentionne juste explicitement puisque les autres réponses ne le font pas. La partie ping de isReachable() nécessite un accès Root sous Unix. Et comme indiqué par bestsss dans 4779367 :

Et si vous demandez pourquoi ping à partir de bash ne le fait pas, en fait, il en a aussi besoin. Faites ce ls -l /bin/ping.

Puisque l'utilisation de Root n'était pas une option dans mon cas, la solution était d'autoriser l'accès au port 7 dans le pare-feu pour le serveur spécifique qui m'intéressait.

0voto

cossoft Points 1

Je dirais que la SEULE façon fiable de tester une connexion Internet est de se connecter réellement ET de télécharger un fichier, OU d'analyser la sortie d'un appel ping de l'OS via exec(). Vous ne pouvez pas compter sur le code de sortie pour ping et isReachable() est une merde.

Vous ne pouvez pas compter sur un code de sortie ping car il renvoie 0 si la commande ping s'exécute correctement. Malheureusement, ping s'exécute correctement s'il ne peut pas atteindre l'hôte cible mais obtient un "Destination host unreachable" de votre routeur ADSL. C'est une sorte de réponse qui est traitée comme un succès, donc le code de sortie = 0. Je dois ajouter que ceci est sur un système Windows. Je n'ai pas vérifié les *nixes.

0voto

col Points 229

Puisque vous pouvez envoyer un ping à l'ordinateur, votre processus Java devrait s'exécuter avec des privilèges suffisants pour effectuer la vérification. Probablement en raison de l'utilisation de ports dans la plage inférieure. Si vous exécutez votre programme java avec sudo/superuser, je parie qu'il fonctionne.

0 votes

Vous n'avez pas besoin de privilège pour connecter aux ports dans la gamme basse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X