Вопрос-ответ

Why does InetAddress.isReachable return false, when I can ping the IP address?

Почему InetAddress.isReachable возвращает false, когда я могу пропинговать 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);

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

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

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


* ПОЖАЛУЙСТА, обратите внимание, что :


  1. Это решение не соответствует производственному качеству. Это своего рода взлом. Если Google не работает, или ваш Интернет временно медленный, или, может быть, даже если в ваших привилегиях / системных настройках есть какая-то странность, if может возвращать ложноотрицательные значения (т. Е. Может произойти сбой, даже если входной адрес доступен).

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

Обновление: Основываясь на недавнем комментарии к этому ответу, вот краткая версия приведенного выше кода:

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 (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 в брандмауэре конкретному серверу, который меня интересовал.

2024-03-04 18:12 java