当我可以 ping 通 IP 地址时,为什么 InetAddress.isReachable 返回 false?

新手上路,请多包涵
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));

为什么 isReachable 返回 false ?我可以ping通IP。

原文由 jiafu 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

在很多情况下, “isReachable” 方法对我来说并不值得使用。您可以滚动到底部以查看我的替代方案,用于简单地测试您是否在线并且能够解析外部主机(即 google.com)……这通常似乎适用于 *NIX 机器。

问题

有很多关于这个的喋喋不休:

  • 这是其他类似的问题:

使用 Java 检测互联网连接

我如何用 Java 测试互联网的可用性?

  • 甚至在同一件事上报告了一个错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4921816

第 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 部分:Hackish 解决方法

作为替代方案,您可以这样做:

 // 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) isReachable 失败是一个突出的问题。再次 - 有几个在线资源表明在撰写本文时没有“完美”的方式来执行此操作,这是由于 JVM 尝试访问主机的方式 - 我想这是一个本质上特定于平台的任务,虽然简单,尚未被 JVM 充分抽象。

原文由 jayunit100 发布,翻译遵循 CC BY-SA 3.0 许可协议

我来这里是为了得到同一个问题的答案,但我对任何答案都不满意,因为我正在寻找一个独立于平台的解决方案。这是我编写的代码,它是独立于平台的,但需要有关另一台机器上任何开放端口的信息(我们大部分时间都有)。

 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;
    }
}

原文由 Sourabh Bhat 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题