¿Cómo comprobar si la conexión a Internet está presente en Java?

¿Cómo verifica si puede conectarse a internet a través de Java? Una forma sería:

final URL url = new URL("http://www.google.com"); final URLConnection conn = url.openConnection(); ... if we got here, we should have net ... 

Pero, ¿hay algo más apropiado para llevar a cabo esa tarea, especialmente si necesita hacer comprobaciones consecutivas con mucha frecuencia y es muy probable una pérdida de conexión a Internet?

Debe conectarse al lugar que necesita su aplicación real. De lo contrario, estás probando si tienes una conexión a algún lugar irrelevante (Google en este caso).

En particular, si intentas hablar con un servicio web y si tienes el control del servicio web, sería una buena idea tener algún tipo de método web barato para obtener el estado. De esta forma, tendrá una idea mucho mejor de si su llamada “real” puede funcionar.

En otros casos, basta con abrir una conexión a un puerto que debería estar abierto, o enviar un ping. InetAddress.isReachable puede ser una API adecuada para sus necesidades aquí.

El código que básicamente proporcionó, más una llamada para connect debería ser suficiente. Así que sí, podría ser que solo Google no está disponible, pero hay algún otro sitio con el que debes contactar, pero ¿qué tan probable es eso? Además, este código solo debe ejecutarse cuando realmente no consigues acceder a tu recurso externo (en un bloque de catch para intentar averiguar cuál fue la causa del error), por lo que diría que si tu recurso externo de interés y Google son no disponible es probable que tenga un problema de conectividad de red.

 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; } } 

La gente sugirió usar INetAddress.isReachable. El problema es que algunos sitios configuran sus firewalls para bloquear los mensajes ICMP Ping. Por lo tanto, un “ping” puede fallar aunque se pueda acceder al servicio web.

Y, por supuesto, lo contrario también es cierto. Un host puede responder a un ping aunque el servidor web esté inactivo.

Y, por supuesto, una máquina puede no ser capaz de conectarse directamente a ciertos (o todos) servidores web debido a las restricciones del firewall local.

El problema fundamental es que “se puede conectar a Internet” es una pregunta mal definida, y este tipo de cosas es difícil de probar sin:

  1. información sobre la máquina del usuario y el entorno de red “local”, y
  2. información sobre a qué necesita acceder la aplicación.

Por lo tanto, en general, la solución más simple es que una aplicación intente acceder a lo que sea necesario para acceder y recurra a la inteligencia humana para hacer el diagnóstico.

Si está en Java 6, puede usar NetworkInterface para verificar las interfaces de red disponibles. Es decir algo como esto:

 Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface interf = interfaces.nextElement(); if (interf.isUp() && !interf.isLoopback()) return true; } 

Aún no lo he probado, todavía.

Este código:

 "127.0.0.1".equals(InetAddress.getLocalHost().getHostAddress().toString()); 

Devuelve – a mí – true si está fuera de línea, y false , de lo contrario. (bueno, no sé si esto es cierto para todas las computadoras).

Esto funciona mucho más rápido que los otros enfoques aquí arriba.


EDIT: encontré que esto solo funciona, si el “interruptor de volteo” (en una computadora portátil) u otra opción definida por el sistema para la conexión a Internet está desactivada. Es decir, el propio sistema sabe que no debe buscar ninguna dirección IP.

Este código debería hacer el trabajo de manera confiable.

Tenga en cuenta que al usar la statement try-with-resources no necesitamos cerrar los recursos.

 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; } } } 

Usualmente lo descompongo en tres pasos.

  1. Primero veo si puedo resolver el nombre de dominio en una dirección IP.
  2. Luego trato de conectarme a través de TCP (puerto 80 y / o 443) y cierro con gracia.
  3. Finalmente, emitiré una solicitud HTTP y comprobaré si hay 200 respuestas.

Si falla en algún momento, proporciono el mensaje de error apropiado al usuario.

 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(); 

Coloque las instrucciones anteriores en los bloques catch de prueba y si una excepción en catch significa que no hay conexión a Internet establecida. 🙂

El código que usa NetworkInterface para esperar la red funcionó para mí hasta que cambié de una dirección de red fija a DHCP. Una ligera mejora lo hace funcionar también con DHCP:

 Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface interf = interfaces.nextElement(); if (interf.isUp() && !interf.isLoopback()) { List adrs = interf.getInterfaceAddresses(); for (Iterator iter = adrs.iterator(); iter.hasNext();) { InterfaceAddress adr = iter.next(); InetAddress inadr = adr.getAddress(); if (inadr instanceof Inet4Address) return true; } } } 

Esto funciona para Java 7 en openSuse 13.1 para la red IPv4. El problema con el código original es que, aunque la interfaz estaba activa después de reanudar desde la suspensión, aún no se había asignado una dirección de red IPv4. Después de esperar esta tarea, el progtwig se puede conectar a los servidores. Pero no tengo idea de qué hacer en caso de IPv6.

InetAddress.isReachable alguna vez devuelve falso si existe conexión a Internet.

Un método alternativo para verificar la disponibilidad de Internet en Java es: Esta función hace que un ICMP ECHO real sea ping.

 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) Averigüe dónde debe conectarse su aplicación.

2) Configure un proceso de trabajo para verificar InetAddress.isReachable para monitorear la conexión a esa dirección.

Este código está dentro de una clase de prueba jUnit que uso para probar si hay una conexión disponible. Siempre recibo una conexión, pero si compruebas la duración del contenido, debería ser -1 si no se conoce:

  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; } 

También hay una opción de --offline que puede dar como resultado el comportamiento que desea.

 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"); } } }