Почему InetAddress.isReachable возвращает false, когда я могу пропинговать IP-адрес? - PullRequest
89 голосов
/ 29 марта 2012
    InetAddress byName = InetAddress.getByName("173.39.161.140");
    System.out.println(byName);
    System.out.println(byName.isReachable(1000));

Почему isReachable возвращает false? Я могу пинговать IP.

Ответы [ 9 ]

70 голосов
/ 13 апреля 2012

Метод "isReachable" во многих случаях мне не подходил.Вы можете прокрутить до конца, чтобы увидеть мой вариант для простого тестирования, если вы подключены к сети и способны разрешать внешние хосты (например, google.com) ... Что обычно работает на машинах * NIX.

Вопрос

Существует много разговоров об этом:

Часть 1. Воспроизводимый пример проблемы

Примечаниечто в этом случае не получается.

       //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*

Часть 2. Обходной путь для взлома

В качестве альтернативы вы можете сделать это:

// 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);

Опция -c ping позволит ping просто попытаться связаться с сервером один раз (в отличие от бесконечного пинга, который мы привыкли использовать в терминале).

Это вернет 0если хост достижим .В противном случае вы получите «2» в качестве возвращаемого значения.

Гораздо проще - но, конечно, это зависит от платформы.И при использовании этой команды могут быть определенные предостережения о привилегиях - но я считаю, что она работает на моих машинах.


ОБРАТИТЕ ВНИМАНИЕ, что: 1) Это решение не является качеством производства.Это немного взломать.Если Google не работает, или ваш интернет временно медленный, или, может быть, даже если в ваших привилегиях / системных настройках есть какая-то забавность, если он может вернуть ложные отрицания (то есть он может потерпеть неудачу, даже если входной адрес доступен).2) Ошибка isReachable является нерешенной проблемой.Опять же - есть несколько онлайн-ресурсов, указывающих, что не существует «идеального» способа сделать это во время написания этой статьи, из-за того, как JVM пытается достичь хостов, - я думаю, что это внутренне специфичная для платформы задача, которая, хотя и проста, еще недостаточно абстрагирован JVM.

44 голосов
/ 11 декабря 2015

Я пришел сюда, чтобы получить ответ на этот же вопрос, но я не был удовлетворен ни одним из ответов, потому что искал независимое от платформы решение. Вот код, который я написал и который не зависит от платформы, но требует информации о любом открытом порту на другом компьютере (который у нас есть большую часть времени).

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;
    }
}
7 голосов
/ 26 июля 2013

Если вы хотите проверить, подключен ли он к Интернету, используйте этот метод, он возвращает значение true, если интернет подключен, предпочтительно, если вы используете адрес сайта, который вы пытаетесь подключить через программу.

     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;
    }
2 голосов
/ 29 сентября 2016

Я не уверен, что было в состоянии, когда первоначальный вопрос был задан еще в 2012 году.

В нынешнем виде ping будет выполняться как root.Через авторизацию исполняемого файла ping вы увидите флаг + s и процесс, принадлежащий root, что означает, что он будет запускаться как root.запустите ls -liat в том месте, где находится пинг, и вы должны его увидеть.

Итак, если вы запустите InetAddress.getByName ("www.google.com"). isReacheable (5000) от имени пользователя root, он должен вернутьtrue.

вам нужны надлежащие полномочия для необработанного сокета, который используется ICMP (протокол, используемый ping)

InetAddress.getByName так же надежен, как и ping, но вам нужны надлежащие разрешения дляпроцесс, чтобы он работал правильно.

2 голосов
/ 10 декабря 2013

Просто упомяну это явно, так как другие ответы не делают.Ping-часть isReachable () требует root-доступа в Unix.И как указывает bestsss в 4779367 :

И если вы спросите, почему ping от bash не нужен, на самом деле это тоже нужно.Сделайте это ls -l /bin/ping.

Поскольку в моем случае использование root не было возможным, решение состояло в том, чтобы разрешить доступ к порту 7 брандмауэра конкретному серверу, который меня интересовал.

0 голосов
/ 18 января 2019

Или используя этот способ:

public static boolean exists(final String host)
{
   try
   {
      InetAddress.getByName(host);
      return true;
   }
   catch (final UnknownHostException exception)
   {
      exception.printStackTrace();
      // Handler
   }
   return false;
}
0 голосов
/ 03 февраля 2017
 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 - количество попыток пинговать ip (пакеты), если вы заняты сетью или системы выбирают более большие номера nping.
wping - это время ожидания pong от ip, вы можете установить его на 2000 мс
для использования этого метода вы можете написать это:

isReachable(5, 2000, "192.168.7.93");
0 голосов
/ 30 сентября 2014

Я бы предположил, что ЕДИНСТВЕННЫЙ надежный способ проверить интернет-соединение - это на самом деле подключиться И загрузить файл, ИЛИ проанализировать вывод ping-вызова ОС через exec (). Вы не можете полагаться на код завершения для ping, а isReachable () - это дерьмо.

Вы не можете полагаться на код завершения ping, так как он возвращает 0, если команда ping выполняется правильно. К сожалению, ping выполняется правильно, если он не может достичь целевого хоста, но получает «целевой хост недоступен» от вашего домашнего ADSL-маршрутизатора. Это своего рода ответ, который рассматривается как успешное нажатие, поэтому код выхода = 0. Необходимо добавить, что это в системе Windows. Не проверено * nixes.

0 голосов
/ 10 января 2014

Поскольку вы можете пропинговать компьютер, ваш Java-процесс должен запускаться с достаточными привилегиями для выполнения проверки. Вероятно, из-за использования портов в нижнем диапазоне. Если вы запустите свою Java-программу с помощью sudo / superuser, я уверен, что она работает.

...