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

jia*_*afu 90 java inetaddress

    InetAddress byName = InetAddress.getByName("173.39.161.140");
    System.out.println(byName);
    System.out.println(byName.isReachable(1000));
Run Code Online (Sandbox Code Playgroud)

为什么要isReachable回来false?我可以ping IP.

jay*_*100 71

在许多情况下,"isReachable"方法并不值得使用.您可以滚动到底部查看我的替代方案,只需测试您是否在线且能够解析外部主机(即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*
Run Code Online (Sandbox Code Playgroud)

第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);
Run Code Online (Sandbox Code Playgroud)

ping的-c选项将允许ping只是尝试到达服务器一次(而不是我们习惯在终端使用的无限ping).

如果主机可访问,则返回0.否则,您将获得"2"作为返回值.

更简单 - 但当然它是特定于平台的.使用此命令可能存在某些特权警告 - 但我发现它可以在我的机器上运行.


请注意:1)此解决方案不是生产质量.它有点像黑客.如果google关闭,或者您的互联网暂时变慢,或者即使您的权限/系统设置中有一些有趣,也可能返回错误的否定(即即使输入地址可以访问也可能失败).2)isReachable失败是一个突出的问题.再次 - 由于JVM尝试访问主机的方式,有几个在线资源表明在撰写本文时没有"完美"的方法 - 我想这是一个本质上特定于平台的任务,尽管很简单,尚未被JVM充分抽象化.

  • @Yuvi如果您使用的是Windows,则标志会有所不同.而不是-c你想要-n. (5认同)
  • Part2解决了我的问题.谢谢你的解决方案. (3认同)

Sou*_*hat 47

我来这里是为了回答同样的问题,但我对任何答案都不满意,因为我一直在寻找一个独立于平台的解决方案.这是我编写的代码并且与平台无关,但需要有关其他机器上任何开放端口的信息(我们大多数时间都是这样).

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很棒的平台独立解决方案,谢谢! (2认同)

Cle*_*anX 7

如果您只想检查它是否连接到互联网使用此方法,如果连接了互联网,则返回true,如果您使用您尝试通过该程序连接的站点的地址,则更可取.

     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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果服务器没有Web服务器,则无用,这根本不是问题中指定的条件。 (2认同)