Обнаружение интернет-соединения с использованием Java
Возможный дубликат:
Как проверить, есть ли интернет-соединение в Java?
Я хочу посмотреть, есть ли у кого-то простой способ определения наличия подключения к Интернету при использовании Java. Текущее приложение использовало метод InternetGetConnectedState в WinInit DLL для Windows, но мое приложение должно быть кросс-платформенным для работы с Mac, и этот способ не будет работать. Я вообще не знаю JNI, чтобы использовать DLL в Java, и это быстро расстраивало.
Единственные способы, которыми я мог придумать, - открыть URL-соединение с веб-сайтом, а если это не удастся, вернуть false. Мой другой путь ниже, но я не знал, было ли это вообще стабильным. Если я отключаю сетевой кабель, я получаю UnknownHostException при попытке создать InetAddress. В противном случае, если кабель подключен, я получаю действительный объект InetAddress. Я еще не тестировал приведенный ниже код на Mac.
Спасибо за любые примеры или советы, которые вы можете предоставить.
ОБНОВЛЕНИЕ: Окончательный блок кода находится внизу. Я решил воспользоваться рекомендацией HTTP-запроса (в данном случае Google). Это просто и отправляет запрос на сайт для данных, которые будут возвращены. Если я не могу получить какой-либо контент из соединения, нет интернета.
public static boolean isInternetReachable()
{
try {
InetAddress address = InetAddress.getByName("java.sun.com");
if(address == null)
{
return false;
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
Окончательный блок кода:
//checks for connection to the internet through dummy request
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 (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
7 ответов
Это совершенно разумный подход к решению проблемы. Плохо то, что вы действительно тестируете DNS, а не тестируете всю сеть, но на практике вы часто можете обходиться, рассматривая их как эквивалентные.
Еще одна вещь, которую нужно помнить, это то, что вам нужно будет установить системное свойство, чтобы отключить кэширование DNS во время выполнения Java. В противном случае он может продолжать сообщать, что сеть работает на основе кэшированных данных (даже если она не работает).
Другой подход заключается в том, чтобы фактически открывать HTTP-запрос к какому-либо сетевому адресу, такому как этот.
Я должен добавить, что, хотя последний приведенный выше кодовый блок хорош, у него есть один недостаток - он может занять очень много времени, чтобы связаться с указанным адресом, но адрес все еще доступен.
В моем случае при тестировании с одним адресом метод возвращал бы значение true, но для получения ответа потребовалось бы 10 секунд или больше. В этом случае сервер был доступен, но не для каких-либо полезных целей, так как соединение было очень медленным. Это происходит потому, что время ожидания по умолчанию для HttpURLConnection
0 или бесконечно.
По этой причине я бы порекомендовал вам проверить поток пользовательского интерфейса и добавить urlConnect.setConnectTimeout(1000);
перед звонком urlConnect.getContent();
Таким образом, вы узнаете, что адрес доступен, и что загрузка файла размером 10 КБ не займет 5 лет.
(Конечно, вы можете изменить время ожидания в соответствии с вашими потребностями)
Также я бы рекомендовал не проверять общий адрес (google.com и т. Д.), Если ваша программа обычно не обращается к нескольким доменам. Если вы просто используете один или два, проверьте этот домен.
Обратите внимание, что он может вернуть false, если java.sun.com не отвечает! В этом случае вы должны проверить другой сайт, чтобы быть уверенным.
Не проверял это, но я предлагаю посмотреть на java.net.NetworkInterface.getNetworkInterfaces(). Это возвращает перечисление всех сетевых интерфейсов на машине или ноль, если их нет.
Я не уверен, можно ли предположить, что ненулевой ответ гарантирует правильное сетевое соединение - в зависимости от ваших потребностей, вам может понадобиться или не потребоваться отфильтровать петлевые адреса (что, я думаю, вы могли бы сделать с java.net.NetworkInterface.getInetAddresses() для каждого возвращенного NetworkInterface, а затем вызывать InetAddress.isLoopbackAddress() для каждого.)
Вопрос на самом деле не имеет смысла. Нет такой вещи как "подключение к Интернету". Вы должны попытаться создать один. Упомянутый Windows API говорит только о том, набран ли ваш модем или нет, и я видел, что это на самом деле вызывает дозвон, что не совсем так. Не то чтобы у меня был дозвон в течение последних 8 лет или около того.
Проблема с первым решением состоит в том, что InetAddress имеет кеш, поэтому, когда вы теряете соединение для следующих нескольких вызовов, имя разрешается через кеш Java. С подключением URL-адреса у вас есть проблема, что вы используете getContent, который должен извлекать html, так что у вас есть потребление данных. Если вызовы выполняются очень часто, это может быть проблемой (особенно если у вас нет неограниченного тарифного плана на устройстве, на котором запущено программное обеспечение).
Я думаю, что лучшим решением было бы установить TCP-соединение с портом 80 и закрыть его сразу после успешного соединения. Это будет вести себя как окончательный код, но будет иметь гораздо меньше трафика.
Единственный способ убедиться в том, что вы можете обратиться к данной услуге, - это сделать фиктивный запрос к этой службе. Пинг может быть заблокирован брандмауэрами. Некоторые серверы могут быть доступны, другие нет. Если вам нужно поговорить с веб-сервисом, создайте статическую страницу для возврата на эти запросы.
Кроме того, не забудьте спросить пользователя, прежде чем пытаться связаться.