Pregunta

¿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 realizar esa tarea, especialmente si tiene que hacer controles consecutivos muy a menudo y es muy probable que se pierda la conexión a Internet?

¿Fue útil?

Solución

Debes conectarte al lugar que tu aplicación real necesita. De lo contrario, está probando si tiene una conexión con algún lugar irrelevante (Google en este caso).

En particular, si está tratando de hablar con un servicio web, y si tiene el control del servicio web, sería una buena idea tener algún tipo de "obtener el estado" barato ". método web De esa manera, tendrá una idea mucho mejor de si su "real" es probable que la llamada funcione.

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í.

Otros consejos

El código que básicamente proporcionó, más una llamada a connect debería ser suficiente. Entonces, sí, podría ser que solo Google no está disponible, pero hay otro sitio con el que debes contactar, pero ¿qué tan probable es eso? Además, este código solo debe ejecutarse cuando realmente no puede acceder a su recurso externo (en un bloque catch para tratar de averiguar cuál fue la causa del error), por lo que diría que si ambos recurso externo de interés y Google no están disponibles, 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;
    }
}

Las personas han sugerido usar INetAddress.isReachable. El problema es que algunos sitios configuran sus firewalls para bloquear los mensajes Ping ICMP. Así que un " ping " puede fallar aunque el servicio web sea accesible.

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

Y, por supuesto, es posible que una máquina no pueda conectarse directamente a ciertos servidores web (o a todos) debido a las restricciones del servidor de seguridad local.

El problema fundamental es que " puede conectarse 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 "local" entorno de redes, y
  2. información sobre a qué necesita acceder la aplicación.

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

Si estás en java 6 puedes usar NetworkInterface para verificar las interfaces de red disponibles. Es decir. algo como esto:

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

Todavía no lo he probado.

Este código:

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

Devuelve - para mí - verdadero si está fuera de línea, y falso , de lo contrario. (bueno, no sé si esto es verdad para todas las computadoras).

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


EDITAR: encontré que esto solo funciona si el " interruptor giratorio " (en una computadora portátil), o alguna otra opción definida por el sistema, para la conexión a Internet, está desactivada. Es decir, el sistema mismo sabe que no debe buscar ninguna dirección IP.

Este código debe hacer el trabajo de manera confiable.

Tenga en cuenta que cuando use try-with-resources declaración 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;
        }
    }
}

Normalmente lo divido en tres pasos.

  1. Primero veo si puedo resolver el nombre de dominio a 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 buscaré una respuesta de 200.

Si falla en cualquier 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 declaraciones anteriores en los bloques try catch y, si se detecta una excepción, significa que no se ha establecido una conexión a Internet. :-)

El código que usa NetworkInterface para esperar la red funcionó hasta que cambié de una dirección de red fija a DHCP. Una leve mejora hace que funcione también con 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;
            }
    }
}

Esto funciona para Java 7 en openSuse 13.1 para 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 asignación, el programa puede conectarse a los servidores. Pero no tengo idea de qué hacer en caso de IPv6.

InetAddress.isReachable en algún momento 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 un ping real de 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) Averigua dónde debe conectarse tu aplicación.

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

Este código está contenido dentro de una clase de prueba jUnit que uso para probar si hay una conexión disponible. Siempre recibo una conexión, pero si verifica la longitud 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 gradle --offline que puede resultar en el comportamiento que desea.

El siguiente fragmento de código nos permite obtener el estado de la red en nuestro dispositivo 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");
            }
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top