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);
Параметр -c команды ping позволит ping просто попытаться связаться с сервером один раз (в отличие от бесконечного ping, который мы привыкли использовать на терминале).
Это вернет 0, если хост доступен . В противном случае вы получите «2» в качестве возвращаемого значения.
Гораздо проще, но, конечно, зависит от платформы. И при использовании этой команды могут быть определенные привилегии, но я считаю, что она работает на моих машинах.
ПОЖАЛУЙСТА, обратите внимание, что: 1) Это решение не является производственным. Это что-то вроде взлома. Если Google не работает, или ваш интернет временно замедлен, или, может быть, даже если в ваших привилегиях / системных настройках есть некоторая забавность, if может вернуть ложноотрицательные результаты (т.е. он может выйти из строя, даже если входной адрес доступен). 2) Ошибка isReachable - нерешенная проблема. Опять же - есть несколько онлайн-ресурсов, указывающих на то, что на момент написания этой статьи не было «идеального» способа сделать это из-за того, как JVM пытается достичь хостов - я предполагаю, что это внутренне зависящая от платформы задача, которая, хотя и проста , JVM еще недостаточно абстрагировала.
isReachable
я получаю ошибку, и с помощью ping я получаю icmp не разрешено? Вы знаете, как теперь с этим бороться?
public boolean waitFor(long timeout, TimeUnit unit)
в java.lang.Process (@since 1.8)
Я пришел сюда, чтобы получить ответ на тот же вопрос, но меня не удовлетворил ни один из ответов, потому что я искал независимое от платформы решение. Вот код, который я написал и не зависит от платформы, но требует информации о любом открытом порте на другом компьютере (который у нас есть большую часть времени).
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;
}
}
InetAddress.isReachable()
уже происходит через порт 7, за исключением того, что последний более интеллектуален в отношении того, что IOExceptions
означают различные возможные с точки зрения достижимости.
InetAddress.isReachable()
был перегружен, чтобы включить аргумент порта в стандартную библиотеку. Интересно, почему его не включили?
Если вы хотите только проверить, подключен ли он к Интернету, используйте этот метод. Он возвращает 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 будет выполняться от имени пользователя root. После авторизации исполняемого файла ping вы увидите флаг + s и процесс, принадлежащий пользователю root, что означает, что он будет работать от имени пользователя root. запустите ls -liat, где находится пинг, и вы должны его увидеть.
Итак, если вы запустите InetAddress.getByName ("www.google.com"). IsReacheable (5000) как root, он должен вернуть true.
вам нужны надлежащие авторизации для сырого сокета, который используется ICMP (протокол, используемый ping)
InetAddress.getByName так же надежен, как ping, но вам нужны соответствующие разрешения для процесса, чтобы он работал правильно.
Я бы предположил, что ЕДИНСТВЕННЫЙ надежный способ проверить подключение к Интернету - это фактически подключиться и загрузить файл, ИЛИ проанализировать вывод ping-вызова ОС через exec (). Вы не можете полагаться на код выхода для ping, а isReachable () - дерьмо.
Вы не можете полагаться на код выхода ping, поскольку он возвращает 0, если команда ping выполняется правильно. К сожалению, ping выполняется правильно, если он не может достичь целевого хоста, но получает сообщение «Целевой хост недоступен» от вашего домашнего ADSL-маршрутизатора. Это своего рода ответ, который обрабатывается как успешное попадание, поэтому код выхода = 0. Но нужно добавить, что это в системе Windows. Не проверял * никсы.
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 - это время ожидания pong с ip, вы можете установить его на 2000 мс
для использования этого метода, вы можете написать это:
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;
}
InetAddress.isReachable
работает нестабильно и иногда возвращает недоступность для адресов, которые мы можем пропинговать.
Я пробовал следующее:
ping -c 1 <fqdn>
и проверьте файл exit status
.
Работает во всех случаях, которые я пробовал, где InetAddress.isReachable
не работает.
Поскольку вы можете проверить связь с компьютером, ваш Java-процесс должен работать с достаточными привилегиями для выполнения проверки. Вероятно, из-за использования портов нижнего диапазона. Если вы запустите свою java-программу с помощью sudo / superuser, я уверен, что она сработает.