2009-07-16 21 views
35

Duplicar posible:
How to check if internet connection is present in java?Detectar conexión a Internet utilizando Java

Quiero ver si alguien tiene una forma fácil de detectar si hay una conexión a Internet cuando se utiliza Java. La aplicación actual usó el método "InternetGetConnectedState" en la DLL WinInit para Windows, pero mi aplicación debe ser multiplataforma para el funcionamiento de mac y de esta manera no funcionará. No sé nada de JNI para usar DLL en Java y se volvió frustrante rápidamente.

Las únicas formas en que podía pensar eran intentar abrir una conexión de URL a un sitio web y, si eso falla, devolver falso. Mi otro camino está abajo, pero no sabía si esto era generalmente estable. Si desenchufo mi cable de red, obtengo una excepción de excepción desconocida cuando trato de crear InetAddress. De lo contrario, si el cable está conectado, obtengo un objeto InetAddress válido. Todavía no he probado el código a continuación en un mac.

Gracias por cualquier ejemplo o consejo que pueda proporcionar.

ACTUALIZACIÓN: El bloque de código final está en la parte inferior. Decidí seguir el consejo de una solicitud HTTP (en este caso, Google). Es simple y envía una solicitud al sitio para que se devuelvan los datos. Si no puedo obtener ningún contenido de la conexión, no hay internet.

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

código final del bloque:

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

Respuesta

17

Eso es un enfoque perfectamente razonable para resolver el problema. Lo malo es que realmente estás probando DNS en lugar de probar toda la red, pero en la práctica a menudo puedes seguir tratando a esos como equivalentes.

Otra cosa que debe recordar, es que deberá configurar una propiedad del sistema para desactivar el almacenamiento en caché de dns en el tiempo de ejecución de java. De lo contrario, puede continuar informando que la red está activa en función de los datos almacenados en caché (aunque esté inactivo).

Otro enfoque sería abrir realmente una solicitud HTTP a alguna dirección de red como esta de vez en cuando.

+0

Gracias por el comentario. Siempre es bueno recibir retroalimentación e ideas diferentes. Pensé en la conexión de URL o en HttpURLConnection para ese asunto. No sabía que esto solo probaba el DNS, pero puede que tenga que vivir con este método. –

+0

Ver el bloque de código final anterior y la nota de actualización. –

3

Tenga en cuenta que podría devolver falso si java.sun.com no responde! En este caso, debe verificar otro sitio para estar seguro.

+0

Buen punto. Creo que es por eso que la versión .NET de esta aplicación usó la DLL para el sistema operativo. De esta forma, el sistema operativo sabía al instante si había una conexión o no, no haciendo ping en los sitios web o revisando los datos. Plantearía la pregunta cuándo trazar la línea. Después de un sitio? ¿Dos? Exactamente por qué quería la entrada. –

2

No he probado esto, pero sugiero mirar java.net.NetworkInterface.getNetworkInterfaces(). Esto devuelve una enumeración de todas las interfaces de red en la máquina, o nula si no hay ninguna.

No estoy seguro de si es seguro asumir que una respuesta no nula garantiza una conexión de red válida. Dependiendo de sus necesidades, puede o no necesitar filtrar direcciones de bucle invertido (lo que creo que podría hacer con java.net.NetworkInterface.getInetAddresses() en cada NetworkInterface devuelto, y luego llamar a InetAddress.isLoopbackAddress() en cada uno.)

2

La única manera de asegurarse de que se puede llegar a un servicio determinado es haciendo un solicitud ficticia a ese servicio. Los pings pueden ser bloqueados por firewalls. Algunos servidores pueden ser accesibles, otros no. Si necesita hablar con un servicio web, tenga una página estática para devolver para estas solicitudes.

Además, recuerde preguntar al usuario antes de tratar de comunicarse.

+0

La única manera en que puede estar seguro es hacer la solicitud * real *. Una solicitud falsa o anterior a la solicitud real podría fallar cuando la real tuviera éxito, o * viceversa *. No puedes predecir el futuro. – EJP

2

La pregunta realmente no tiene un significado. No existe una "conexión a Internet". Tienes que intentar crear uno. La API de Windows a la que se hace referencia solo le dice si su módem está marcado o no, y lo he visto en realidad causa 0-dial-ins, que no es exactamente la idea. No es que haya tenido un dial-in durante los últimos 8 años más o menos.

+0

Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar aclaraciones de un autor, deje un comentario debajo de su publicación. –

+1

@IanLim La respuesta aquí es 'tienes que intentar crear uno', y está de acuerdo con la mayoría de los demás. – EJP

2

Un problema con la primera solución es que InetAddress tiene una memoria caché, por lo que, cuando pierde la conexión para las próximas invocación, el nombre se resuelve mediante la memoria caché de Java. Con el enfoque de conexión de URL, tiene el problema de que usa getContent que debe recuperar html para que tenga consumo de datos. Si las invocaciones se realizan con mucha frecuencia, esto podría ser un problema (más aún si no tiene un plan de datos ilimitado en el dispositivo que ejecuta el software).

Creo que la mejor solución sería hacer una conexión TCP al puerto 80 y cerrarlo inmediatamente después de una conexión exitosa. Eso se comportaría como el código final pero tendría mucho menos tráfico.

11

Debo agregar que aunque el bloque de código final dado arriba es bueno, tiene un defecto: es posible que tome mucho tiempo contactar la dirección especificada, pero la dirección todavía es accesible.

En mi caso, cuando probaba con una dirección, el método devolvía verdadero, pero demoraba 10 segundos o más para obtener una respuesta. En este caso, el servidor era alcanzable, pero no con fines útiles ya que la conexión era muy lenta. Esto ocurre porque el tiempo de espera predeterminado para HttpURLConnection es , o infinito.

Por esta razón me gustaría recomendar que hacer la revisión el hilo de interfaz de usuario, y añadir urlConnect.setConnectTimeout(1000);antes de llamarurlConnect.getContent();

De esta manera se conoce la dirección es accesible, y que no se llevará a 5 años para descargar un archivo de 10k.

(Es posible, por supuesto, quieren cambiar el tiempo el tiempo de espera para que se adapte a sus necesidades)

También me gustaría recomendar no comprobar una dirección genérica (google.com, etc) a menos que su programa general accede a más de unos pocos dominios Si solo está accediendo a uno o dos, verifique ese dominio.

+0

Este es un hecho muy importante a tener en cuenta. Tuve que enfrentar este problema mientras probaba la aplicación en la máquina virtual. Y tomó años para obtener la conexión. El tiempo de espera de conexión es vital en este caso, entonces. – Indigo

+0

considera agregar tiempo de espera puede ser importante en algún momento. – Vishrant

Cuestiones relacionadas