¿Por qué InetAddress.isReachable devuelve falso, cuando puedo hacer ping a la dirección IP?

InetAddress byName = InetAddress.getByName("173.39.161.140"); System.out.println(byName); System.out.println(byName.isReachable(1000)); 

¿Por isReachable retorno de isReachable false ? Puedo hacer ping a la IP.

El método “isReachable” no ha sido útil para mí en muchos casos. Puede desplazarse hacia abajo para ver mi alternativa para simplemente probar si está en línea y es capaz de resolver hosts externos (es decir, google.com) … Lo cual generalmente parece funcionar en máquinas * NIX.

La cuestión

Hay mucha charla sobre esto:

Parte 1: Un ejemplo reproducible del problema

Tenga en cuenta que en este caso, falla.

  //also, this fails for an invalid address, like "www.sjdosgoogle.com1234sd" InetAddress[] addresses = InetAddress.getAllByName("www.google.com"); for (InetAddress address : addresses) { if (address.isReachable(10000)) { System.out.println("Connected "+ address); } else { System.out.println("Failed "+address); } } //output:*Failed www.google.com/74.125.227.114* 

Parte 2: una solución provisional de Hackish

Como alternativa, puedes hacer esto:

 // in case of Linux change the 'n' to 'c' Process p1 = java.lang.Runtime.getRuntime().exec("ping -n 1 www.google.com"); int returnVal = p1.waitFor(); boolean reachable = (returnVal==0); 

La opción -c de ping permitirá que ping simplemente intente llegar al servidor una vez (a diferencia del ping infinito que estamos acostumbrados a usar en la terminal).

Esto devolverá 0 si el host es alcanzable . De lo contrario, obtendrás “2” como valor de retorno.

Mucho más simple, pero por supuesto es específico de la plataforma. Y puede haber ciertas advertencias de privilegio al usar este comando, pero creo que funciona en mis máquinas.


TEN EN CUENTA que: 1) Esta solución no es de calidad de producción. Es un poco complicado. Si Google está inactivo, o su Internet es temporalmente lento, o tal vez incluso si hay algo de gracia en sus privilegios / configuración del sistema, podría devolver falsos negativos (es decir, podría fallar incluso si la dirección de entrada es alcanzable). 2) La falla de isReachable es un problema pendiente. Nuevamente, hay varios recursos en línea que indican que no existe una forma “perfecta” de hacerlo en el momento de escribir este documento, debido a la forma en que la JVM intenta llegar a los hosts. Supongo que es una tarea intrínsecamente específica de la plataforma que, aunque simple , aún no ha sido suficientemente abstraído por la JVM.

Vine aquí para obtener una respuesta para esta misma pregunta, pero no estaba satisfecho con ninguna de las respuestas porque estaba buscando una solución independiente de la plataforma. Aquí está el código que escribí y es independiente de la plataforma, pero requiere información sobre cualquier puerto abierto en la otra máquina (que tenemos la mayoría del tiempo).

 private static boolean isReachable(String addr, int openPort, int timeOutMillis) { // Any Open port on other machine // openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc. try { try (Socket soc = new Socket()) { soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis); } return true; } catch (IOException ex) { return false; } } 

Si solo desea comprobar si está conectado a Internet, utilice este método. Devuelve verdadero si Internet está conectado. Es preferible si utiliza la dirección del sitio que está intentando conectar a través del progtwig.

  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 (Exception e) { e.printStackTrace(); return false; } return true; } 

Solo mencionarlo explícitamente ya que las otras respuestas no lo hacen. La parte de ping de isReachable () requiere acceso de root en Unix. Y como se señala por bestsss en 4779367 :

Y si preguntas por qué ping de bash no lo hace, en realidad también lo necesita. Haz eso ls -l / bin / ping.

Como usar root no era una opción en mi caso, la solución era permitir el acceso al puerto 7 en el firewall al servidor específico que me interesaba.

No estoy seguro de cuál era el estado cuando se formuló la pregunta original en 2012.

Tal como está ahora, ping se ejecutará como una raíz. A través de la autorización del ejecutable de ping verá el indicador + s, y el proceso perteneciente a la raíz, lo que significa que se ejecutará como raíz. ejecuta ls -liat en donde se encuentra el ping y deberías verlo.

Por lo tanto, si ejecuta InetAddress.getByName (“www.google.com”). IsReacheable (5000) como raíz, debería devolver true.

necesita las autorizaciones adecuadas para el socket bruto, que es utilizado por ICMP (el protocolo utilizado por ping)

InetAddress.getByName es tan confiable como ping, pero necesita los permisos adecuados en el proceso para que se ejecute correctamente.

Sugeriría que la ÚNICA manera confiable de probar una conexión a Internet es conectar AND descargar un archivo, O analizar la salida de una llamada ping del SO a través de exec (). No puede confiar en el código de salida para ping y isReachable () es una mierda.

No puede confiar en un código de salida de ping ya que devuelve 0 si el comando ping se ejecuta correctamente. Lamentablemente, el ping se ejecuta correctamente si no puede llegar al host de destino, pero obtiene un “host de destino inalcanzable” de su enrutador ADSL de origen. Esta es una especie de respuesta que se trata como un éxito, por lo tanto, el código de salida es 0. Tengo que agregar que esto está en un sistema Windows. No verificado * nixes.

  private boolean isReachable(int nping, int wping, String ipping) throws Exception { int nReceived = 0; int nLost = 0; Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("ping -n " + nping + " -w " + wping + " " + ipping); Scanner scanner = new Scanner(process.getInputStream()); process.waitFor(); ArrayList strings = new ArrayList<>(); String data = ""; // while (scanner.hasNextLine()) { String string = scanner.nextLine(); data = data + string + "\n"; strings.add(string); } if (data.contains("IP address must be specified.") || (data.contains("Ping request could not find host " + ipping + ".") || data.contains("Please check the name and try again."))) { throw new Exception(data); } else if (nping > strings.size()) { throw new Exception(data); } int index = 2; for (int i = index; i < nping + index; i++) { String string = strings.get(i); if (string.contains("Destination host unreachable.")) { nLost++; } else if (string.contains("Request timed out.")) { nLost++; } else if (string.contains("bytes") && string.contains("time") && string.contains("TTL")) { nReceived++; } else { } } return nReceived > 0; } 

nping es el número de bashs de hacer ping a ip (paquetes), si tiene una red o sistemas ocupados, elija números biger nping.
wping es el tiempo esperando pong desde ip, puedes configurarlo 2000ms
para usar este método puedes escribir esto:

 isReachable(5, 2000, "192.168.7.93"); 

Como puede hacer ping a la computadora, su proceso Java debe ejecutarse con privilegios suficientes para realizar la comprobación. Probablemente debido al uso de puertos en el rango inferior. Si ejecuta su progtwig java con sudo / superuser, apuesto a que funciona.