2008-10-12 22 views
11

Me gustaría obtener la función más rápida y precisa boolean isReachable(String host, int port) que pase las siguientes pruebas de JUnit en las condiciones siguientes. Los valores de tiempo de espera se especifican mediante la prueba JUnit en sí misma, y ​​pueden considerarse "inalcanzables".¿Cuál es la forma más rápida de detectar un host inalcanzable en Java?

Tenga en cuenta: Todas las respuestas deben ser independientes de la plataforma. Esto significa que InetAddress.isReachable(int timeout) no funcionará, ya que depende del puerto 7 para hacer un ping en Windows (ICMP ping es una función no documentada en Windows), y este puerto está bloqueado en esta configuración. Configuración

LAN:

  • thisMachine (192.168.0.100)
  • otherMachine (192.168.0.200)
  • ninguna máquina se llama noMachine o tiene la IP 192.168.0.222 (siempre inalcanzable)
  • ambas máquinas están funcionando Apache Tomcat en el puerto 8080; todos los demás puertos son inalcanzables (incluyendo el puerto 7)
  • example.com (208.77.188.166) se está ejecutando un servidor web en el puerto 80 y es solamente accesible cuando la LAN está conectado a Internet

De vez en cuando, la LAN está desconectado de la Internet, en cuyo caso solo se puede acceder a las máquinas locales llamadas por dirección IP (no se puede acceder a todas las demás, no hay DNS).

Todas las pruebas se ejecutan en thisMachine.

@Test(timeout=1600) // ~320ms per call (should be possible to do better) 
public void testLocalhost() { 
    // We can always reach ourselves. 
    assertTrue(isReachable("localhost", 8080)); 
    assertTrue(isReachable("127.0.0.1", 8080)); 
    assertTrue(isReachable("thisMachine", 8080)); // Even if there's no DNS! 
    assertTrue(isReachable("192.168.0.100", 8080)); 

    assertFalse(isReachable("localhost", 80)); // Nothing on that port. 
} 

@Test(timeout=5500) // ~1867ms per call (should be able to do better) 
public void testLAN() { 
    assertTrue(isReachable("192.168.0.200", 8080)); // Always connected to the LAN. 
    assertFalse(isReachable("192.168.0.222", 8080)); // No such a machine. 
    assertFalse(isReachable("noMachine", 8080)); // No such machine. 
} 

La siguiente prueba sólo se ejecuta cuando la LAN está desconectado desde Internet.

@Test(timeout=5600) // ~1867ms per call (reasonable?) 
public void testNoDNS() { 
    assertFalse(isReachable("otherMachine", 8080)); // No DNS. 
    assertFalse(isReachable("example.com", 80)); // No DNS & no Internet. 
    assertFalse(isReachable("208.77.188.166", 80)); // No Internet. 
} 

La siguiente prueba sólo se ejecuta cuando la LAN está conectada a Internet.

@Test(timeout=5600) // ~1867ms per call (reasonable?) 
public void testHaveDNS() { 
    assertTrue(isReachable("otherMachine", 8080)); // DNS resolves local names. 
    assertTrue(isReachable("example.com", 80)); // DNS available. 
    assertTrue(isReachable("208.77.188.166", 80)); // Internet available. 
} 

Respuesta

0

Mi solución depende más reciente utilizando un TimedSocket (source code) con 3000 ms de tiempo de espera mientras se realiza una conexión.

Tiempos:

  • 1406ms: testLocalHost()
  • 5280ms: testLAN()

ni siquiera puede conseguir éstos funcionen correctamente:

  • testNoDNS()
  • testHaveDNS()
0

No estoy seguro de lo práctico que es esto.

¿Qué le parece hacer el equivalente de traceroute (tracert en Windows) y una vez que tenga éxito, puede continuar.

En las redes corporativas, he visto ICMP (ping) bloqueado por los administradores PERO generalmente, tracert todavía funciona. Si puede encontrar una forma rápida de hacer lo que tracert hace, ¿debería funcionar?

¡Buena suerte!

1

Si desea probar si puede conectarse a un servidor web también se puede crear un URL basado en el nombre de host y el número de puerto y la usará para crear un URLConnection comprobar el resultado (incluidas las excepciones) de la connect method debe decirle si el servidor web es alcanzable.

5

En primer lugar debe reconocer que tiene potencialmente requisitos conflictivos; Los enchufes IP no son deterministas en el tiempo. Lo más rápido que puede detectar la falta de acceso es después de su tiempo de espera transcurrido. Solo puedes detectar la accesibilidad más rápido.

Suponiendo accesibilidad/isReachable es su objetivo real, sólo debe utilizar un sencillo conector sin bloqueo IO como se muestra en el simulador Java Ping, el ejemplo se conecta al servicio de tiempo, pero funcionaría igual de bien en 8080.

0

Si necesita hacer esto con una gran cantidad de hosts en un período de tiempo muy breve, consideraría utilizar una herramienta como fping en su lugar, pagar para ejecutarla y analizar el resultado cuando vuelva. fping ejecuta una gran cantidad de consultas paralelas a la vez, por lo que podría verificar miles de hosts en un minuto (creo que el límite es 4096)

0

El paso de determinación de la tasa de disponibilidad del host no está dentro de su propio código, pero en el netlag. Debe esperar a que el host responda, y esto puede llevar tiempo. Si su programa se bloquea mientras espera una respuesta, podría ser un problema. Lo solucioné creando cada host como un objeto, cada uno con su propio método de subprocesos para verificar la disponibilidad. En mi propia situación, tengo 40 hosts de los que hago un seguimiento. Mi programa principal recorre una matriz de 40 objetos de máquina una vez cada 20 segundos, llamando al método apropiado para verificar la disponibilidad. Como cada objeto de máquina genera su propio hilo para hacer esto, las 40 máquinas se interrogan simultáneamente y el tiempo de respuesta (hasta 500 ms) para cada uno no es un problema.

Cuestiones relacionadas