为什么 InetAddress.isReachable 在我可以 ping IP 地址时返回 false?
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
为什么会回来?我可以 ping IP。isReachable
false
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
为什么会回来?我可以 ping IP。isReachable
false
在许多情况下,“可访问”方法不值得我使用。您可以滚动到底部以查看我的替代方案,以简单地测试您是否在线并且能够解析外部主机(即 google.com)...这通常似乎适用于*NIX机器。
问题
有很多关于这个的喋喋不休:
以下是其他类似的问题:
甚至在同一问题上报告了一个错误:
第1部分:问题的可重现示例
请注意,在这种情况下,它将失败。
//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*
第2部分:黑客解决方法
作为替代方案,您可以执行此操作:
// 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);
ping的-c选项将允许ping简单地尝试到达服务器一次(而不是我们习惯于在终端上使用的无限ping)。
如果主机可访问,这将返回 0。否则,您将获得“2”作为返回值。
简单得多 - 但当然它是特定于平台的。使用此命令可能有某些特权警告 - 但我发现它适用于我的机器。
请注意:1)此解决方案不是生产质量。这有点像黑客。如果谷歌关闭,或者您的互联网暂时变慢,或者即使您的权限/系统设置中存在一些有趣之处,如果可能返回假阴性(即,即使输入地址可访问,它也可能失败)。2) 可访问故障是一个未解决的问题。再次 - 有几个在线资源表明,由于JVM尝试访问主机的方式,在撰写本文时没有“完美”的方法可以做到这一点 - 我想这是一个本质上是特定于平台的任务,虽然很简单,但尚未被JVM充分抽象。
我来这里是为了得到同一个问题的答案,但我对任何答案都不满意,因为我正在寻找一个独立于平台的解决方案。这是我编写的代码,与平台无关,但需要有关另一台计算机上任何开放端口的信息(我们大部分时间都有)。
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;
}
}
更新:根据最近对此答案的评论,以下是上述代码的简洁版本:
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 (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
return true;
} catch (IOException ex) {
return false;
}
}