2009-07-16 3 views
35

Можно создать дубликат:
How to check if internet connection is present in java?Обнаружение подключения к Интернету с помощью Java

Я хочу, чтобы увидеть, если кто-то имеет простой способ обнаружения, если есть подключение к Интернету при использовании Java. Текущее приложение использовало метод InternetGetConnectedState в библиотеке WinInit для 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; 
     } 

ответ

17

Это вполне разумный подход к решению этой проблемы. Плохо то, что вы действительно тестируете DNS, а не тестируете всю сеть, но на практике вы часто можете справиться с этим, как эквивалент.

Другое, что нужно помнить, это то, что вам нужно будет установить системное свойство, чтобы отключить кэширование DNS в среде java. В противном случае он может продолжать сообщать, что сеть основана на кэшированных данных (даже если она не работает).

Другим подходом было бы фактически открыть HTTP-запрос на какой-либо сетевой адрес, такой как каждый раз так часто.

+0

Спасибо за комментарий. Всегда полезно получать обратную связь и разные идеи. Я подумал о соединении с URL-адресом или с помощью HttpURLConnection. Я не знал, что это проверено только DNS, но мне, возможно, придется жить с этим методом. – 2009-07-16 18:59:15

+0

См. Заключительный блок кода выше и примечание по обновлению. – 2009-07-16 19:39:30

3

Обратите внимание, что он может вернуть значение false, если java.sun.com не отвечает! В этом случае вы должны проверить другой сайт, чтобы быть уверенным.

+0

Хорошая точка. Я думаю, именно поэтому версия .NET этого приложения использовала DLL для ОС. Таким образом, операционная система сразу же узнала, есть ли соединение или нет, а не пинг веб-сайтов или проверка паролей. Это поставило бы вопрос, когда нужно провести линию. После одного сайта? Два? Именно поэтому мне нужен вход. – 2009-07-16 19:06:50

2

Не проверял это, но я предлагаю посмотреть на java.net.NetworkInterface.getNetworkInterfaces(). Это возвращает перечисление всех сетевых интерфейсов на машине или null, если их нет.

Я не уверен, можно ли предположить, что непузырный ответ обеспечивает действительное сетевое соединение - в зависимости от ваших потребностей вам может понадобиться или не нужно отфильтровать петлевые адреса (которые, я думаю, вы могли бы сделать с java.net.NetworkInterface.getInetAddresses() на каждом возвращенном NetworkInterface, а затем вызовите InetAddress.isLoopbackAddress() для каждого из них.)

2

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

Кроме того, не забудьте спросить пользователя, прежде чем пытаться протянуть руку.

+0

Единственный способ, которым вы можете быть уверенным, - сделать запрос * real *. Фиктивный запрос orior для реального запроса может завершиться неудачно, когда реальный будет успешным, или * наоборот *. Вы не можете предсказать будущее. – EJP

2

Вопрос не имеет значения. Нет такой вещи, как «подключение к Интернету». Вы должны попробовать создать один. В упомянутом выше API Windows упоминается только, набирается ли ваш модем или нет, и я видел, что на самом деле вызывает dial-ins, что не совсем так. Не то, чтобы у меня был набор номера в течение последних 8 лет или около того.

+0

Это не дает ответа на вопрос. Чтобы критиковать или просить разъяснения у автора, оставьте комментарий ниже их сообщения. –

+1

@IanLim Ответ guven здесь - «вы должны попытаться создать его», и он согласен с большинством других. – EJP

2

Проблема с первым решением заключается в том, что InetAddress имеет кэш, поэтому, когда вы теряете соединение для следующих нескольких вызовов, имя разрешается через кеш java. С помощью URL-адреса aproach у вас возникла проблема с использованием getContent, который должен извлекать html, чтобы у вас было потребление данных. Если вызовы выполняются очень часто, это может быть проблемой (более того, если у вас нет неограниченного плана данных на устройстве, на котором запущено программное обеспечение).

Я думаю, что лучшим решением было бы сделать TCP-соединение с портом 80 и закрыть его после успешного соединения. Это будет вести себя как окончательный код, но будет иметь гораздо меньше трафика.

11

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

В моем случае при тестировании с одним адресом метод вернул бы true, но занять 10 секунд или больше, чтобы получить ответ. В этом случае сервер был доступен, но не для каких-либо полезных целей, так как соединение было настолько медленным. Это происходит потому, что тайм-аут по умолчанию для HttpURLConnection равен , или бесконечный.

По этой причине я рекомендую вам проверить все, от потока пользовательского интерфейса, а также добавить urlConnect.setConnectTimeout(1000);перед тем вызывающему urlConnect.getContent();

Таким образом, вы знаете адрес достижим, и что это не займет 5 лет для загрузки файла 10k.

(Вы можете, конечно, хотите изменить время тайм-аута в соответствии с вашими потребностями)

Кроме того, я рекомендовал бы не проверить общий адрес (google.com и т.д.), если ваша программа вообще не обращается к более чем несколько домены. Если вы просто получаете доступ к одному или двум, проверьте этот домен.

+0

Это очень важный факт, который следует учитывать. Мне пришлось столкнуться с этой проблемой при тестировании приложения на виртуальной машине. И взял возраст, чтобы получить соединение. Тайм-аут соединения в этом случае жизненно необходим. – Indigo

+0

рассмотреть вопрос о добавлении таймаута, это может быть важно когда-нибудь. – Vishrant

Смежные вопросы