InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Почему isReachable
возвращает false
? Я могу выполнить IP-адрес.
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Почему isReachable
возвращает false
? Я могу выполнить IP-адрес.
Метод 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.
Я пришел сюда, чтобы получить ответ на этот же вопрос, но я был недоволен любым из ответов, потому что я искал платформо-независимое решение. Вот код, который я написал и независим от платформы, но требует информации о любом открытом порту на другом компьютере (который мы имеем большую часть времени).
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;
}
}
Если вы хотите только проверить, подключен ли он к интернету, этот метод возвращает значение 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;
}
Просто упомянуть об этом явно, так как другие ответы не отвечают. Для ping-части isReachable() требуется root-доступ в Unix. И как указано в bestsss в 4779367:
И если вы спросите, почему ping из bash нет, на самом деле это тоже нужно. Сделайте это ls -l/bin/ping.
Так как использование root не было вариантом, в моем случае решение заключалось в том, чтобы разрешить доступ к порту 7 в брандмауэре на конкретный сервер, который меня интересовал.
Я не уверен, каково было состояние, когда исходный вопрос был задан в 2012 году.
Как сейчас, ping будет выполняться как корень. Через исполняемый файл ping вы увидите флаг + s и процесс, принадлежащий root, то есть он будет запущен с правами root. запустите ls -liat, где находится пинг, и вы должны его увидеть.
Итак, если вы запустите InetAddress.getByName( "www.google.com" ). isReacheable (5000) с правами root, он должен вернуть true.
вам нужны правильные разрешения для raw-сокета, который используется ICMP (протокол, используемый ping)
InetAddress.getByName так же надежно, как и ping, но вам нужны правильные разрешения для процесса, чтобы он работал правильно.
Я бы предположил, что ТОЛЬКО надежный способ протестировать подключение к Интернету - это фактически подключиться и загрузить файл, или разобрать вывод вызова ping с помощью exec(). Вы не можете полагаться на код выхода для ping и isReachable() - это дерьмо.
Вы не можете полагаться на код выхода ping, поскольку он возвращает 0, если команда ping выполняется правильно. К сожалению, ping выполняется правильно, если он не может дойти до целевого хоста, но получает "Destination host unreachable" от вашего домашнего ADSL-маршрутизатора. Это своего рода ответ, который обрабатывается как успешный хит, поэтому выходим из кода = 0. Имейте в виду, что это относится к системе Windows. Не проверено * nixes.
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");
Или используя этот способ:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
Поскольку вы можете пинговать компьютер, ваш Java-процесс должен работать с достаточными полномочиями для выполнения проверки. Возможно, из-за использования портов в нижнем диапазоне. Если вы запустите свою java-программу с помощью sudo/superuser, я буду держать пари, что она работает.