InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Pourquoi isReachable
revient-il false
? Je peux cingler l'IP.
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Pourquoi isReachable
revient-il false
? Je peux cingler l'IP.
Réponses:
La méthode "isReachable" n'a pas été digne d'être utilisée pour moi dans de nombreux cas. Vous pouvez faire défiler vers le bas pour voir mon alternative pour simplement tester si vous êtes en ligne et capable de résoudre des hôtes externes (ie google.com) ... Ce qui semble généralement fonctionner sur les machines * NIX.
Le problème
Il y a beaucoup de discussions à ce sujet:
Voici d'autres questions similaires:
Et même un bug signalé sur ce même sujet:
Partie 1: Un exemple reproductible du problème
Notez que dans ce cas, il échoue.
//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*
Partie 2: Une solution de contournement hackish
Comme alternative, vous pouvez faire ceci:
// 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'option -c de ping permettra à ping d'essayer simplement d'atteindre le serveur une fois (par opposition au ping infini que nous avons l'habitude d'utiliser sur le terminal).
Cela renverra 0 si l'hôte est accessible . Sinon, vous obtiendrez "2" comme valeur de retour.
Beaucoup plus simple - mais bien sûr, c'est spécifique à la plate-forme. Et il peut y avoir certaines réserves de privilèges à utiliser cette commande - mais je trouve que cela fonctionne sur mes machines.
VEUILLEZ noter que: 1) Cette solution n'est pas une qualité de production. C'est un peu un hack. Si Google est en panne, ou votre Internet est temporairement lent, ou peut-être même si vos privilèges / paramètres système sont amusants, cela pourrait renvoyer de faux négatifs (c'est-à-dire que cela pourrait échouer même si l'adresse d'entrée est accessible). 2) L'échec isReachable est un problème en suspens. Encore une fois - il existe plusieurs ressources en ligne indiquant qu'il n'y a pas de moyen «parfait» de le faire au moment de la rédaction de cet article, en raison de la façon dont la JVM tente d'atteindre les hôtes - je suppose que c'est une tâche intrinsèquement spécifique à la plate-forme qui, bien que simple , n'a pas encore été suffisamment abstraite par la JVM.
isReachable
et que j'utilise le ping, je reçois icmp non autorisé? Savez-vous comment y faire face maintenant?
public boolean waitFor(long timeout, TimeUnit unit)
dans java.lang.Process (@since 1.8)
Je suis venu ici pour obtenir une réponse à cette même question, mais je n'étais satisfait d'aucune des réponses car je cherchais une solution indépendante de la plate-forme. Voici le code que j'ai écrit et est indépendant de la plate-forme, mais nécessite des informations sur tout port ouvert sur l'autre machine (que nous avons la plupart du temps).
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()
déjà, via le port 7, sauf que ce dernier est plus intelligent sur ce que les différents possibles IOExceptions
signifient en termes d'accessibilité.
InetAddress.isReachable()
était surchargé d'inclure l'argument port, dans la bibliothèque standard. Je me demande pourquoi il n'a pas été inclus?
Si vous souhaitez uniquement vérifier s'il est connecté à Internet, utilisez cette méthode, il renvoie true si Internet est connecté, il est préférable si vous utilisez l'adresse du site que vous essayez de vous connecter via le programme.
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;
}
Il suffit de le mentionner explicitement puisque les autres réponses ne le font pas. La partie ping de isReachable () nécessite un accès root sous Unix. Et comme indiqué par bestsss dans 4779367 :
Et si vous demandez pourquoi le ping de bash ne le fait pas, il en a également besoin. Faites cela ls -l / bin / ping.
Étant donné que l'utilisation de root n'était pas une option dans mon cas, la solution était d'autoriser l'accès au port 7 du pare-feu au serveur spécifique qui m'intéressait.
Je ne sais pas dans quel état était la question lorsque la question initiale a été posée en 2012.
Dans l'état actuel des choses, le ping sera exécuté en tant que root. Grâce à l'autorisation de l'exécutable ping, vous verrez l'indicateur + s et le processus appartenant à root, ce qui signifie qu'il fonctionnera en tant que root. lancez ls -liat sur l'emplacement du ping et vous devriez le voir.
Ainsi, si vous exécutez InetAddress.getByName ("www.google.com"). IsReacheable (5000) en tant que root, il doit renvoyer true.
vous avez besoin des autorisations appropriées pour le socket brut, qui est utilisé par ICMP (le protocole utilisé par ping)
InetAddress.getByName est aussi fiable que ping, mais vous avez besoin des autorisations appropriées sur le processus pour qu'il fonctionne correctement.
Je suggérerais que le SEUL moyen fiable de tester une connexion Internet est de se connecter ET de télécharger un fichier, OU d'analyser la sortie d'un appel ping du système d'exploitation via exec (). Vous ne pouvez pas compter sur le code de sortie pour le ping et isReachable () est de la merde.
Vous ne pouvez pas vous fier à un code de sortie ping car il renvoie 0 si la commande ping s'exécute correctement. Malheureusement, le ping s'exécute correctement s'il ne peut pas atteindre l'hôte cible mais obtient un «hôte de destination inaccessible» de votre routeur ADSL domestique. C'est une sorte de réponse qui est traitée comme un succès, donc le code de sortie = 0. Il faut ajouter cependant que c'est sur un système Windows. Non vérifié * 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 est le nombre d'essais de ping sur ip (paquets), si vous avez un réseau ou des systèmes occupés, choisissez des nombres plus élevés.
wping est le temps d'attente pour pong d'ip, vous pouvez le définir à 2000 ms
pour utiliser cette méthode, vous pouvez écrire ceci:
isReachable(5, 2000, "192.168.7.93");
Ou en utilisant cette façon:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
est flappy, et renvoie parfois inaccessible pour les adresses auxquelles nous pouvons envoyer un ping.
J'ai essayé ce qui suit:
ping -c 1 <fqdn>
et vérifiez le exit status
.
Fonctionne pour tous les cas que j'avais essayés où InetAddress.isReachable
ne fonctionne pas.
Étant donné que vous pouvez exécuter une requête ping sur l'ordinateur, votre processus Java doit s'exécuter avec des privilèges suffisants pour effectuer la vérification. Probablement en raison de l'utilisation de ports dans la plage inférieure. Si vous exécutez votre programme java avec sudo / superuser, je parie que cela fonctionne.