read - use sockets in java
¿Cuál es la forma más rápida de detectar un host inalcanzable en Java? (6)
En primer lugar, debe reconocer que tiene requisitos potencialmente 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.
Asumiendo accesibilidad / isReachable es su objetivo real, debe usar un IO de socket directo sin bloqueo como se muestra en el simulador Java Ping , el ejemplo se conecta con el servicio horario pero funcionaría igual de bien en 8080.
Me gustaría que la función boolean isReachable(String host, int port)
más rápida y precisa pase las siguientes pruebas JUnit bajo las condiciones que se boolean isReachable(String host, int port)
continuación. Los valores de tiempo de espera se especifican mediante la prueba JUnit en sí misma, y pueden considerarse "inalcanzables".
Tenga en cuenta: todas las respuestas deben ser independientes de la plataforma. Esto significa que InetAddress.isReachable(int timeout)
no va a 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 de LAN:
-
thisMachine
(192.168.0.100
) -
otherMachine
(192.168.0.200
) - ninguna máquina se llama
noMachine
o tiene la IP192.168.0.222
(siempre inalcanzable) - ambas máquinas ejecutan Apache Tomcat en el puerto
8080
; todos los otros puertos son inalcanzables (incluido el puerto7
) -
example.com
(208.77.188.166
) ejecuta un servidor web en el puerto80
y solo es accesible cuando la LAN está conectada a Internet.
Ocasionalmente, la LAN se desconecta de 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 solo se ejecuta cuando la LAN está desconectada de 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 solo 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.
}
Si necesita hacer esto con una gran cantidad de hosts en un período de tiempo muy breve, consideraría usar una herramienta como fping en su lugar: shell out para ejecutarla y analizar el resultado cuando vuelva. fping ejecuta una gran cantidad de consultas paralelas a la vez, por lo que teóricamente puedes verificar unos pocos miles de hosts en un minuto (¿creo que el límite es 4096?)
Mi solución más reciente depende de usar un TimedSocket
( código fuente ) con 3000 ms de tiempo de espera mientras realizo una conexión.
Tiempos:
- 1406ms:
testLocalHost()
- 5280ms:
testLAN()
Ni siquiera puedo hacer que funcionen correctamente:
-
testNoDNS()
-
testHaveDNS()
No estoy seguro de lo práctico que es esto.
¿Qué hay de hacer el equivalente de traceroute (tracert en Windows) y una vez que tenga un éxito, puede continuar.
En redes corporativas, he visto ICMP (ping) bloqueado por 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!
Si desea probar si puede conectarse a un servidor web, también puede crear una URL basada en el nombre de host y el número de puerto y usarla para crear una URLConnection, verificando el resultado (incluidas las excepciones) del método de conexión debería decirle si el servidor web es alcanzable.
El paso de determinación de velocidad para la disponibilidad del host no está dentro de su propio código, sino 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.