Как проверить, есть ли интернет-соединение в Java?
-
05-07-2019 - |
Вопрос
Как проверить, можно ли подключиться к Интернету через Java? Один из способов будет:
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
... if we got here, we should have net ...
Но есть ли что-то более подходящее для выполнения этой задачи, особенно , если вам нужно выполнять последовательные проверки очень часто и вероятность подключения к Интернету высока? р>
Решение
Вы должны подключиться к месту, в котором нуждается ваше реальное приложение. В противном случае вы проверяете, есть ли у вас связь с чем-то несущественным (в данном случае Google).
В частности, если вы пытаетесь поговорить с веб-службой и если вы контролируете веб-службу, было бы неплохо иметь какой-то дешевый " получить статус " веб-метод. Таким образом, у вас будет гораздо лучшее представление о том, является ли ваш "реальным" звонок скорее всего сработает.
В других случаях достаточно просто открыть соединение с портом, который должен быть открыт, или отправить пинг. InetAddress.isReachable
вполне может быть подходящим API для ваших нужд здесь.
Другие советы
Код, который вы в основном предоставили, плюс вызов connect
должен быть достаточным. Так что да, может быть, просто Google не доступен, но есть другой сайт, с которым вам нужно связаться, но насколько вероятно это? Кроме того, этот код должен выполняться только тогда, когда вы фактически не можете получить доступ к своему внешнему ресурсу (в блоке catch
, чтобы попытаться выяснить причину сбоя), поэтому я бы сказал, что если оба ваших Интересующие внешние ресурсы и Google недоступны, скорее всего, у вас проблема с сетевым подключением.
private static boolean netIsAvailable() {
try {
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
conn.connect();
conn.getInputStream().close();
return true;
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
return false;
}
}
Люди предложили использовать INetAddress.isReachable. Проблема в том, что некоторые сайты настраивают свои брандмауэры для блокировки сообщений ICMP Ping. Так что "пинг" может произойти сбой, даже если веб-сервис доступен. Р>
И, конечно, верно и обратное. Хост может ответить на эхо-запрос, даже если веб-сервер не работает.
И, конечно, машина может быть не в состоянии подключиться напрямую к определенным (или всем) веб-серверам из-за локальных ограничений брандмауэра.
Основная проблема заключается в том, что "можно подключиться к Интернету" является плохо определенным вопросом, без которого трудно проверить такие вещи:
<Ол>В общем, самое простое решение для приложения - просто попытаться получить доступ ко всему, что ему нужно, и прибегнуть к человеческому интеллекту для постановки диагноза.
Если вы работаете в java 6, вы можете использовать NetworkInterface проверить наличие доступных сетевых интерфейсов. То есть как то так:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface interf = interfaces.nextElement();
if (interf.isUp() && !interf.isLoopback())
return true;
}
Сам пока не пробовал.
Этот код:
"127.0.0.1".equals(InetAddress.getLocalHost().getHostAddress().toString());
Возвращает - мне - true
в автономном режиме и false
в противном случае. (ну, я не знаю, правда ли это для всех компьютеров). Р>
Это работает намного быстрее, чем другие подходы, здесь.
<Ч>РЕДАКТИРОВАТЬ: я обнаружил, что это работает только в том случае, если переключатель <" (на ноутбуке) или какой-либо другой системный параметр для подключения к Интернету отключен. То есть сама система знает, что не нужно искать никаких IP-адресов.
Этот код должен выполнять работу надежно.
Обратите внимание, что при использовании try-with-resources
, нам не нужно закрывать ресурсы.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class InternetAvailabilityChecker
{
public static boolean isInternetAvailable() throws IOException
{
return isHostAvailable("google.com") || isHostAvailable("amazon.com")
|| isHostAvailable("facebook.com")|| isHostAvailable("apple.com");
}
private static boolean isHostAvailable(String hostName) throws IOException
{
try(Socket socket = new Socket())
{
int port = 80;
InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
socket.connect(socketAddress, 3000);
return true;
}
catch(UnknownHostException unknownHost)
{
return false;
}
}
}
Обычно я разбиваю его на три этапа.
<Ол>Если в любой момент происходит сбой, я предоставляю соответствующее сообщение об ошибке пользователю.
URL url=new URL("http://[any domain]");
URLConnection con=url.openConnection();
/*now errors WILL arise here, i hav tried myself and it always shows "connected" so we'll open an InputStream on the connection, this way we know for sure that we're connected to d internet */
/* Get input stream */
con.getInputStream();
Поместите вышеприведенные операторы в блоки try catch, и если исключение в catch означает, что подключение к Интернету не установлено. : -)
Код, использующий NetworkInterface для ожидания сети, работал для меня, пока я не переключился с фиксированного сетевого адреса на DHCP. Небольшое улучшение позволяет работать и с DHCP:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface interf = interfaces.nextElement();
if (interf.isUp() && !interf.isLoopback()) {
List<InterfaceAddress> adrs = interf.getInterfaceAddresses();
for (Iterator<InterfaceAddress> iter = adrs.iterator(); iter.hasNext();) {
InterfaceAddress adr = iter.next();
InetAddress inadr = adr.getAddress();
if (inadr instanceof Inet4Address) return true;
}
}
}
Это работает для Java 7 в openSuse 13.1 для сети IPv4. Проблема с исходным кодом заключается в том, что, хотя интерфейс был отключен после возобновления из режима ожидания, сетевой адрес IPv4 еще не был назначен. После ожидания этого назначения программа может подключаться к серверам. Но я понятия не имею, что делать в случае IPv6. Р>
InetAddress.isReachable
иногда возвращает false, если интернет-соединение существует. Р>
Альтернативный метод проверки доступности интернета в java: эта функция делает реальный пинг ICMP ECHO
.
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch( Exception e ) {
e.printStackTrace();
return false;
}
}
1) Выясните, где ваше приложение должно подключаться.
2) Настройте рабочий процесс для проверки InetAddress.isReachable для отслеживания соединения с этим адресом.
Этот код содержится в тестовом классе jUnit, который я использую, чтобы проверить, доступно ли соединение. Я всегда получаю соединение, но если вы проверите длину контента, оно должно быть -1, если не известно:
try {
URL url = new URL("http://www.google.com");
URLConnection connection = url.openConnection();
if(connection.getContentLength() == -1){
fail("Failed to verify connection");
}
}
catch (IOException e) {
fail("Failed to open a connection");
e.printStackTrace();
}
public boolean checkInternetConnection()
{
boolean status = false;
Socket sock = new Socket();
InetSocketAddress address = new InetSocketAddress("www.google.com", 80);
try
{
sock.connect(address, 3000);
if(sock.isConnected()) status = true;
}
catch(Exception e)
{
status = false;
}
finally
{
try
{
sock.close();
}
catch(Exception e){}
}
return status;
}
Существует также опция Gradle - offline
, которая может привести к желаемому поведению.
Следующий фрагмент кода позволяет нам получить статус сети на нашем устройстве Android
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView mtv=findViewById(R.id.textv);
ConnectivityManager connectivityManager=
(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(((Network)connectivityManager.getActiveNetwork())!=null)
mtv.setText("true");
else
mtv.setText("fasle");
}
}
}