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 просто спробувати дістатися до сервера один раз (на відміну від нескінченного пінгу, який ми звикли використовувати на терміналі).
Це поверне 0, якщо хост доступний . В іншому випадку ви отримаєте "2" як повернене значення.
Набагато простіше - але, звичайно, це залежить від платформи. І можуть бути певні застереження щодо використання цієї команди, але я вважаю, що це працює на моїх машинах.
ВАЖЛИВО, зверніть увагу, що: 1) Це рішення не є якістю виробництва. Це трохи хак. Якщо Google не працює, або ваш Інтернет тимчасово працює повільно, або, можливо, навіть якщо у ваших привілеях / налаштуваннях системи є якась забава, якщо це може повернути помилкові негативи (тобто це може не вдатися, навіть якщо вхідна адреса доступна). 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()
перевантажити включення аргументу порту у стандартну бібліотеку. Цікаво, чому його не включили?
Якщо ви хочете лише перевірити, чи підключений він до Інтернету, використовуйте цей метод, він повертає істину, якщо підключений Інтернет. Бажано, якщо ви використовуєте адресу веб-сайту, який ви намагаєтеся підключити через програму.
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;
}
Просто прямо згадуючи це, оскільки інші відповіді цього не роблять. Пінг-частина isReachable () вимагає кореневого доступу в Unix. І як зазначив bestsss у 4779367 :
І якщо ви запитаєте, чому пінг з bash цього не робить, насправді це теж потрібно. Зробіть це ls -l / bin / ping.
Оскільки в моєму випадку використання root не було варіантом, рішення полягало в тому, щоб дозволити доступ до порту 7 у брандмауері до конкретного сервера, який мене цікавив.
Я не впевнений, яким був стан, коли оригінальне питання було задано ще в 2012 році.
Як зараз, ping буде виконуватися як root. Через авторизацію виконуваного файлу ping ви побачите прапор + s і процес, що належить root, тобто він буде виконуватися як root. запустіть ls -liat там, де знаходиться пінг, і ви повинні його побачити.
Отже, якщо ви запустили InetAddress.getByName ("www.google.com"). IsReacheable (5000) як корінь, він повинен повернути true.
вам потрібні належні дозволи для вихідного сокета, який використовується ICMP (протокол, який використовує ping)
InetAddress.getByName настільки ж надійний, як і ping, але вам потрібні належні дозволи на процес, щоб він працював належним чином.
Я б припустив, що ЄДИНИЙ надійний спосіб перевірити підключення до Інтернету - це насправді підключитися І завантажити файл, АБО проаналізувати вихідні дані виклику пінгу ОС через exec (). Ви не можете покладатися на код виходу для ping, і isReachable () є глупством.
Ви не можете покладатися на код виходу ping, оскільки він повертає 0, якщо команда ping виконується правильно. На жаль, ping виконується правильно, якщо він не може досягти цільового хоста, але отримує "Кінцевий хост недоступний" від вашого домашнього маршрутизатора 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 - це кількість спроб пінгувати ip (пакети), якщо у вас зайнята мережа або системи, вибирайте більші числа nping.
wping - це час очікування на понг від 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, я впевнений, що це працює.