web-dev-qa-db-fra.com

Pourquoi InetAddress.isReachable renvoie-t-il false lorsque je peux envoyer une requête ping à l'adresse IP?

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

Pourquoi isReachable renvoie-t-il false? Je peux cingler l'IP.

85
jiafu

La méthode "isReachable" n'a pas été digne de m'utiliser dans de nombreux cas. Vous pouvez faire défiler l'écran vers le bas pour voir mon alternative. Vous pouvez simplement tester si vous êtes en ligne et capable de résoudre des hôtes externes (par exemple, google.com) ... Ce qui semble généralement fonctionner sur les ordinateurs * NIX.

Le problème

Il y a beaucoup de discussions à ce sujet:

Partie 1: Exemple reproductible du problème

Notez que dans ce cas, cela é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: Solution de rechange pour le piratage

Au lieu de cela, 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 simplement de joindre le serveur une fois (contrairement au ping infini que nous utilisons habituellement au terminal).

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

Beaucoup plus simple - mais bien sûr, cela dépend de la plateforme. Et il peut y avoir certaines mises en garde sur les privilèges d'utilisation de cette commande - mais je trouve que cela fonctionne sur mes machines.


S'IL VOUS PLAÎT noter que: 1) Cette solution n'est pas de qualité de production. C'est un peu un bidouillage. Si Google est en panne ou si votre connexion Internet est temporairement lente, ou peut-être même si vos privilèges/paramètres système sont quelque peu amusants, ils peuvent renvoyer de faux négatifs (c’est-à-dire qu’ils peuvent échouer même si l’adresse d’entrée est accessible). 2) L’échec d’isReachable est une question en suspens. Encore une fois, plusieurs ressources en ligne indiquent qu’il n’existe pas de méthode "parfaite" pour le faire au moment de la rédaction de cet article, en raison de la façon dont la machine virtuelle tente d’atteindre les hôtes. Je suppose que c’est une tâche intrinsèquement spécifique à la , n’a pas encore été suffisamment analysé par la machine virtuelle.

71
jayunit100

Je suis venu ici pour obtenir une réponse à la même question, mais je n’étais pas satisfait des réponses car je recherchais une solution indépendante de la plate-forme. Voici le code que j'ai écrit et qui est indépendant de la plate-forme, mais nécessite des informations sur tout port ouvert sur l'autre machine (que nous avons la plupart du temps).

private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
    // Any Open port on other machine
    // openPort =  22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
    try {
        try (Socket soc = new Socket()) {
            soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
        }
        return true;
    } catch (IOException ex) {
        return false;
    }
}
40
Sourabh Bhat

Si vous souhaitez uniquement vérifier s'il est connecté à Internet, utilisez cette méthode. Il renvoie true si Internet est connecté. Il est préférable si vous utilisez l'adresse du site que vous essayez de connecter via 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;
    }
7
CleanX

Il suffit de le mentionner 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 le souligne bestsss dans 4779367

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

Comme l’utilisation de root n’était pas une option dans mon cas, la solution consistait à autoriser l’accès au port 7 du pare-feu au serveur spécifique qui m’intéressait.

2
Zitrax

Je ne sais pas dans quel état se trouvait la question initiale posée en 2012.

Dans l'état actuel des choses, ping sera exécuté en tant que racine. Grâce à l'autorisation de l'exécutable ping, vous verrez l'indicateur + s et le processus appartenant à root, ce qui signifie qu'il s'exécutera en tant que root. lancez ls -liat sur l'emplacement du ping et vous devriez le voir.

Ainsi, si vous exécutez InetAddress.getByName ("www.google.com"). IsReacheable (5000) en tant que root, il doit renvoyer la valeur true.

vous avez besoin d'autorisations appropriées pour le socket brut, qui est utilisé par ICMP (le protocole utilisé par ping)

InetAddress.getByName est aussi fiable que ping, mais vous devez disposer d'autorisations appropriées sur le processus pour qu'il fonctionne correctement.

2
Clebert Suconic

Je suggérerais que le SEUL moyen fiable de tester une connexion Internet consiste à se connecter ET à télécharger un fichier, OR, afin d'analyser la sortie d'un appel ping du système d'exploitation via exec (). Vous ne pouvez pas compter sur le code de sortie pour ping et isReachable () is crap.

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 "hôte de destination inaccessible" de votre routeur ADSL domestique. C'est une sorte de réponse qui est traitée comme un hit réussi, donc code de sortie = 0. Il faut ajouter que c'est sur un système Windows. Non vérifié * nixes.

0
cossoft
 private boolean isReachable(int nping, int wping, String ipping) throws Exception {

    int nReceived = 0;
    int nLost = 0;

    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec("ping -n " + nping + " -w " + wping + " " + ipping);
    Scanner scanner = new Scanner(process.getInputStream());
    process.waitFor();
    ArrayList<String> strings = new ArrayList<>();
    String data = "";
    //
    while (scanner.hasNextLine()) {
        String string = scanner.nextLine();
        data = data + string + "\n";
        strings.add(string);
    }

    if (data.contains("IP address must be specified.")
            || (data.contains("Ping request could not find Host " + ipping + ".")
            || data.contains("Please check the name and try again."))) {
        throw new Exception(data);
    } else if (nping > strings.size()) {
        throw new Exception(data);
    }

    int index = 2;

    for (int i = index; i < nping + index; i++) {
        String string = strings.get(i);
        if (string.contains("Destination Host unreachable.")) {
            nLost++;
        } else if (string.contains("Request timed out.")) {
            nLost++;
        } else if (string.contains("bytes") && string.contains("time") && string.contains("TTL")) {
            nReceived++;
        } else {
        }
    }

    return nReceived > 0;
}

nping est le nombre de tentatives de ping sur ip (paquets), si votre réseau ou vos systèmes sont occupés, choisissez biger nping numbers . 
wping est le temps d'attente pour pong de l'ip, vous pouvez le définir 2000ms
pour utiliser cette méthode, vous pouvez écrire ceci:

isReachable(5, 2000, "192.168.7.93");
0
Armin Mokri

Ou en utilisant cette façon:

public static boolean exists(final String Host)
{
   try
   {
      InetAddress.getByName(Host);
      return true;
   }
   catch (final UnknownHostException exception)
   {
      exception.printStackTrace();
      // Handler
   }
   return false;
}
0
Yousha Aleayoub