Почему InetAddress.isReachable возвращает false, когда я могу выполнить ping IP-адрес?

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

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

Ответ 1

Метод 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);

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

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

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


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

Ответ 2

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

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;
    }
}

Ответ 3

Если вы хотите только проверить, подключен ли он к интернету, этот метод возвращает значение 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;
    }

Ответ 4

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

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

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

Ответ 5

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

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

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

вам нужны правильные разрешения для raw-сокета, который используется ICMP (протокол, используемый ping)

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

Ответ 6

Я бы предположил, что ТОЛЬКО надежный способ протестировать подключение к Интернету - это фактически подключиться и загрузить файл, или разобрать вывод вызова ping с помощью exec(). Вы не можете полагаться на код выхода для ping и isReachable() - это дерьмо.

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

Ответ 7

 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 - это число попыток ping ip (пакетов), если у вас занята сеть или системы, выберите более крупные номера nping.
wping - это время ожидания понга от ip, вы можете установить его на 2000 мс
 для использования этого метода u можете написать это:

isReachable(5, 2000, "192.168.7.93");

Ответ 8

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

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

Ответ 9

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