InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Perché isReachable
ritorna false
? Posso eseguire il ping dell'IP.
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Perché isReachable
ritorna false
? Posso eseguire il ping dell'IP.
Risposte:
Il metodo "isReachable" non è stato degno di essere utilizzato in molti casi. Puoi scorrere fino in fondo per vedere la mia alternativa per testare semplicemente se sei online e in grado di risolvere host esterni (ad esempio google.com) ... Che generalmente sembra funzionare su macchine * NIX.
Il problema
Ci sono molte chiacchiere su questo:
Ecco altre domande simili:
E anche un bug segnalato su questo stesso argomento:
Parte 1: un esempio riproducibile del problema
Nota che in questo caso fallisce.
//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 soluzione alternativa alla pirateria informatica
In alternativa, puoi farlo:
// 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);
L'opzione -c di ping consentirà a ping di tentare semplicemente di raggiungere il server una volta (al contrario del ping infinito che siamo abituati a usare al terminale).
Questo restituirà 0 se l'host è raggiungibile . Altrimenti, otterrai "2" come valore di ritorno.
Molto più semplice, ma ovviamente è specifico della piattaforma. E potrebbero esserci alcuni avvertimenti sui privilegi nell'utilizzo di questo comando, ma trovo che funzioni sulle mie macchine.
SI PREGA di notare che: 1) Questa soluzione non è la qualità della produzione. È un po 'un trucco. Se Google è inattivo, o la tua connessione Internet è temporaneamente lenta, o forse anche se c'è qualche stranezza nei tuoi privilegi / impostazioni di sistema, potrebbe restituire falsi negativi (cioè potrebbe non riuscire anche se l'indirizzo di input è raggiungibile). 2) L'errore isReachable è un problema in sospeso. Ancora una volta - ci sono diverse risorse online che indicano che non esiste un modo "perfetto" per farlo al momento della stesura di questo articolo, a causa del modo in cui la JVM cerca di raggiungere gli host - immagino che sia un'attività intrinsecamente specifica della piattaforma che, sebbene semplice , non è stato ancora sufficientemente astratto dalla JVM.
isReachable
se sto fallendo e usando ping ottengo icmp non consentito? Sai come affrontarlo adesso?
public boolean waitFor(long timeout, TimeUnit unit)
in java.lang.Process (@since 1.8)
Sono venuto qui per ottenere una risposta alla stessa domanda, ma nessuna delle risposte mi ha soddisfatto perché stavo cercando una soluzione indipendente dalla piattaforma. Ecco il codice che ho scritto ed è indipendente dalla piattaforma, ma richiede informazioni su qualsiasi porta aperta sull'altra macchina (che abbiamo la maggior parte del tempo).
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()
già fa, tramite la porta 7, tranne che quest'ultima è più intelligente su cosa IOExceptions
significano i vari possibili in termini di raggiungibilità.
InetAddress.isReachable()
fosse sovraccaricato per includere l'argomento port, nella libreria standard. Mi chiedo perché non fosse incluso?
Se vuoi solo controllare se è connesso ad internet usa questo metodo, restituisce vero se internet è connesso, è preferibile se usi l'indirizzo del sito che stai cercando di connetterti tramite il programma.
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;
}
Menzionandolo esplicitamente poiché le altre risposte no. La parte ping di isReachable () richiede l'accesso come root su Unix. E come sottolineato da bestsss in 4779367 :
E se chiedi perché ping da bash non lo fa, in realtà ne ha bisogno. Fallo ls -l / bin / ping.
Poiché l'utilizzo di root non era un'opzione nel mio caso, la soluzione era consentire l'accesso alla porta 7 nel firewall al server specifico a cui ero interessato.
Non sono sicuro di quale fosse lo stato quando è stata posta la domanda originale nel 2012.
Allo stato attuale, il ping verrà eseguito come root. Tramite l'autorizzazione dell'eseguibile ping vedrai il flag + se il processo che appartiene a root, il che significa che verrà eseguito come root. esegui ls -liat su dove si trova il ping e dovresti vederlo.
Quindi, se esegui InetAddress.getByName ("www.google.com"). IsReacheable (5000) come root, dovrebbe restituire true.
sono necessarie le autorizzazioni appropriate per il raw socket, che viene utilizzato da ICMP (il protocollo utilizzato da ping)
InetAddress.getByName è affidabile come il ping, ma sono necessarie le autorizzazioni appropriate per il processo per farlo funzionare correttamente.
Suggerirei che l'UNICO modo affidabile per testare una connessione Internet è di connettersi e scaricare effettivamente un file, OPPURE analizzare l'output di una chiamata ping del sistema operativo tramite exec (). Non puoi fare affidamento sul codice di uscita per il ping e isReachable () è una schifezza.
Non puoi fare affidamento su un codice di uscita ping poiché restituisce 0 se il comando ping viene eseguito correttamente. Sfortunatamente, il ping viene eseguito correttamente se non riesce a raggiungere l'host di destinazione ma ottiene un "Host di destinazione irraggiungibile" dal router ADSL di casa. Questa è una specie di risposta che viene trattata come un successo di successo, quindi il codice di uscita = 0. Devo aggiungere però che questo è su un sistema Windows. Non verificato * 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 è il numero di tentativi di ping ip (pacchetti), se hai una rete occupata o sistemi scegli numeri di nping più grandi.
wping è tempo di attesa di pong da ip, puoi impostarlo a 2000 ms
per usare questo metodo puoi scrivere questo:
isReachable(5, 2000, "192.168.7.93");
O usando in questo modo:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
è instabile e talvolta restituisce irraggiungibile per gli indirizzi che possiamo eseguire il ping.
Ho provato quanto segue:
ping -c 1 <fqdn>
e controlla il file exit status
.
Funziona per tutti i casi che ho provato dove InetAddress.isReachable
non funziona.
Poiché è possibile eseguire il ping del computer, il processo Java dovrebbe essere eseguito con privilegi sufficienti per eseguire il controllo. Probabilmente a causa dell'utilizzo di porte nella fascia inferiore. Se esegui il tuo programma java con sudo / superuser, scommetto che funziona.