InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
¿Por qué isReachable
vuelve false
? Puedo hacer ping a la IP.
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
¿Por qué isReachable
vuelve false
? Puedo hacer ping a la IP.
Respuestas:
El método "isReachable" no ha sido digno de usar para mí en muchos casos. Puede desplazarse hasta la parte inferior para ver mi alternativa para simplemente probar si está en línea y es capaz de resolver hosts externos (es decir, google.com) ... que generalmente parece funcionar en máquinas * NIX.
La cuestión
Hay mucha charla sobre esto:
Aquí hay otras preguntas similares:
E incluso un error informado sobre este mismo asunto:
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 hackish
Como alternativa, puede 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 accesible . De lo contrario, obtendrá "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 para usar este comando, pero encuentro que funciona en mis máquinas.
TENGA EN CUENTA QUE: 1) Esta solución no es de calidad de producción. Es un truco. Si Google está inactivo, o su Internet está 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 aunque la dirección de entrada sea accesible). 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 hacer esto en el momento de escribir este artículo, 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 extraído lo suficiente por la JVM.
isReachable
si estoy fallando y usando ping, ¿no se permite icmp? ¿Sabes cómo lidiar con eso ahora?
public boolean waitFor(long timeout, TimeUnit unit)
en java.lang.Process (@since 1.8)
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 parte 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;
}
}
InetAddress.isReachable()
ya hace, a través del puerto 7, excepto que este último es más inteligente sobre lo que los diversos posibles IOExceptions
significan en términos de accesibilidad.
InetAddress.isReachable()
se sobrecargara para incluir el argumento del puerto, en la biblioteca estándar. Me pregunto por qué no estaba incluido.
Si solo desea verificar si está conectado a Internet, use este método. Devuelve verdadero si Internet está conectado. Es preferible si usa la dirección del sitio al que está intentando conectarse a través del programa.
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 mencionándolo explícitamente ya que las otras respuestas no lo hacen. La parte de ping de isReachable () requiere acceso de root en Unix. Y como lo señala bestsss en 4779367 :
Y si pregunta por qué el ping de bash no lo hace, en realidad también lo necesita. Haz eso ls -l / bin / ping.
Dado que usar root no era una opción en mi caso, la solución fue permitir el acceso al puerto 7 en el firewall para el servidor específico que me interesaba.
No estoy seguro de cuál era el estado cuando se hizo la pregunta original en 2012.
Tal como está ahora, ping se ejecutará como root. A través de la autorización del ejecutable ping, verá el indicador + s, y el proceso que pertenece a root, lo que significa que se ejecutará como root. ejecute ls -liat donde se encuentra el ping y debería verlo.
Por lo tanto, si ejecuta InetAddress.getByName ("www.google.com"). IsReacheable (5000) como root, debería devolver verdadero.
necesita las autorizaciones adecuadas para el socket sin procesar, 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 forma confiable de probar una conexión a Internet es conectarse Y descargar un archivo, O analizar la salida de una llamada de ping del sistema operativo a través de exec (). No puede confiar en el código de salida para hacer ping e 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. Desafortunadamente, el ping se ejecuta correctamente si no puede alcanzar el host de destino, pero obtiene un "Host de destino inalcanzable" de su enrutador ADSL doméstico. Esta es una especie de respuesta que se trata como un acierto exitoso, por lo tanto, código de salida = 0. Sin embargo, debo agregar que esto es en un sistema Windows. No marcado * 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<String> 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 intentos de hacer ping a ip (paquetes), si tiene una red o sistemas ocupados, elija números de nping más grandes.
wping es el tiempo de espera para pong desde ip, puede configurarlo en 2000ms
para usar este método, puede escribir esto:
isReachable(5, 2000, "192.168.7.93");
O usando de esta manera:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
es flappy y, a veces, devuelve inalcanzable para direcciones a las que podemos hacer ping.
Intenté lo siguiente:
ping -c 1 <fqdn>
y compruebe el exit status
.
Funciona para todos los casos que probé donde InetAddress.isReachable
no funciona.
Como puede hacer ping a la computadora, su proceso de Java debe ejecutarse con privilegios suficientes para realizar la verificación. Probablemente debido al uso de puertos en el rango inferior. Si ejecuta su programa java con sudo / superuser, apuesto a que funciona.