2012-03-29 425 views
78
InetAddress byName = InetAddress.getByName("173.39.161.140"); 
    System.out.println(byName); 
    System.out.println(byName.isReachable(1000)); 

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

+0

可能重复:http://stackoverflow.com/questions/ 4779367 /问题与难以到达的在inetaddress类 – assylias 2012-03-29 09:32:14

+1

它是相似的。但我找不到解决问题的线索。所以我在这里重新评估了它。感谢您的提醒! – jiafu 2012-03-29 12:18:37

+1

我会尝试增加超时。 – jayunit100 2012-04-13 17:01:23

回答

66

“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* 

第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); 

的-c选项将允许平简单地尝试到达服务器一次(而不是我们以前在终端上使用的无限ping)。

这将返回如果主机可到达。否则,您将得到“2”作为返回值。

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


请注意: 1)该溶液是不生产质量。它有点黑客。如果谷歌关闭,或者你的网络暂时很慢,或者甚至在你的特权/系统设置中有一些乐趣,如果可能返回错误的否定(即使输入地址可达,它也可能失败)。 2)isReachable失败是一个突出的问题。再说一遍 - 有几个在线资源表明,在写这篇文章时,由于JVM尝试访问主机的方式,没有“完美”的方式来做这件事 - 我想这是一个固有的平台特定任务,尽管它很简单,尚未被JVM充分抽象。

+0

非常感谢你! – jiafu 2012-04-13 23:22:16

+0

@ jayunit100这两种方法都不工作,'isReachable'我失败了,使用ping我得到icmp不允许?你知道现在如何处理它吗? – Yuvi 2013-01-07 08:58:22

+5

@Yuvi如果您使用Windows,则标志会有所不同。而不是-c你想要-n。 – 2013-10-21 22:31:39

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

如果服务器没有web服务器,这是没有规定的条件在这个问题上。 – 2014-12-04 14:14:25

2

只是明确提到它,因为其他答案没有。 isReachable()的ping部分在Unix上需要root访问权限。正如4779367中的bestss所指出的那样:

如果你问为什么从bash中ping不出来,实际上它确实也需要。做那个ls -l/bin/ping。

由于使用根源是不是在我的情况选择解决办法是允许访问端口7防火墙到特定服务器我感兴趣的

-1

既然可以ping计算机,您的Java过程应以足够的权限运行以执行检查。可能由于使用较低范围的端口。如果你用sudo/superuser运行你的java程序,我敢打赌它的工作原理。

+0

您不需要特权* *连接*到低范围的端口。 – EJP 2015-06-03 06:03:48

0

我建议测试互联网连接的唯一可靠方法是实际连接并下载文件,或通过exec()解析OS ping调用的输出。你不能依靠ping的退出代码,isReachable()是废话。

如果ping命令正确执行,则不能依赖ping退出代码,因为它返回0。不幸的是,如果ping无法到达目标主机,但是从家庭ADSL路由器获取“目标主机不可达”,ping将正确执行。这是一种被视为成功命中的回复,因此退出代码= 0.必须添加,但这是在Windows系统上。未检查* nixes。

30

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

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

谢谢,这是工作! – Butsaty 2015-12-25 05:25:35

+2

这是一个很好的平台独立解决方案,谢谢! – ivandov 2016-02-17 19:02:21

+1

我很高兴我在这里结束了,很好的思考Sourabh :) – OmarBizreh 2016-03-12 20:43:48

1

我不知道是什么时候了原来的问题被要求回到2012年

目前的情况是,中国平安将作为根被执行的状态。通过ping可执行文件的授权,您将看到+ s标志以及属于root的进程,这意味着它将以root身份运行。运行ls -liat在ping的位置,你应该看到它。

因此,如果您以超级用户身份运行InetAddress.getByName(“www.google.com”)。isReacheable(5000),它应该返回true。

你需要的原始套接字,它使用ICMP(ping所使用的协议)

InetAddress.getByName是平安可靠适当的授权,但你需要在过程中适当的权限运行它正常。

0
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是尝试ping IP(数据包)的数量,如果你有繁忙的网络或系统选择比格尔nping号码。
wping是时候从IP等待乒乓球,你可以将它设置2000毫秒
使用这种方法ü可以这样写:

isReachable(5, 2000, "192.168.7.93"); 
相关问题