用于ping测量的isReachable()方法返回错误的值

时间:2014-02-16 09:36:15

标签: java eclipse ping

我正在尝试使用Java的isReachable()方法来测量我的电脑和服务器之间的ping延迟。到目前为止,我一直在使用这种方法:

 Process p1 = Runtime.getRuntime().exec("ping -n 1 " + indIP);
    int pingValue = 0;

    long t1 = System.currentTimeMillis();
    try {

        p1.waitFor();

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    long t2 = System.currentTimeMillis();


    int exit = p1.exitValue();
    if (exit==0){
        pingValue = (int) (t2-t1);
        return pingValue;
    }
    else
        return -1;

但是我注意到它返回的值高于使用CMD获得的ping值(大约+ 10ms)。

所以我尝试使用InetAddress提供的方法,但值似乎完全错误。

以下是代码:

 String servername = "xx.xx.xx.xx";

    InetAddress addr = InetAddress.getByName(servername);
    long currentTime = System.currentTimeMillis();
    boolean pingOK = addr.isReachable(2000);
    currentTime = System.currentTimeMillis() - currentTime;
    if(pingOK) {
        System.out.println("Ping: "+ currentTime+ " ms");
    } else {
        System.out.println("Ping failed.");
    }

例如,如果我尝试通过CMD对服务器执行ping操作,则会获得9-10ms,但此方法会为同一服务器返回100倍的值,或者根本不起作用。我在Stackoverflow上看了一下其他线程,但我找不到任何能让我的ping检查更准确的内容。

提前感谢您的时间。

编辑:通过定义另一种“测量”系统延迟的方法,我得到了更准确的值:

public static int getSysLatency() throws IOException{
     long t3 = System.currentTimeMillis();

        Process p2 = Runtime.getRuntime().exec("ping -n 1 127.0.0.1");

        try {
            p2.waitFor();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        t3 = System.currentTimeMillis()-t3;

        return (int) t3;
}

这种情况下的延迟应该<1ms,因此在调用Process p1 = Runtime.getRuntime().exec("ping -n 1 " + indIP);时我可以让系统“延迟”。

然后我将t3减去pingValue,我得到了更好的延迟值,这几乎与通过CMD显示的相同。

1 个答案:

答案 0 :(得分:1)

请参阅此Stack Overflow问题:Why does InetAddress.isReachable return false, when I can ping the IP address?和本文:http://bordet.blogspot.com/2006/07/icmp-and-inetaddressisreachable.html

简而言之,ping使用ICMP,但isReachable()通常不会。 Windows不能正确支持ICMP,Linux / Unix支持它但需要root权限。在这两种情况下,isReachable()回退到在端口7上进行TCP调用,这可能会因为此端口经常关闭而失败。如果它没有失败,它的行为与ping的行为完全不同,正如您所注意到的那样。

我知道的最佳解决方案是使用ping通过Runtime.getRuntime().exec(),就像您的原始代码一样,这是特定于平台但“有效”的。上面的Stack Overflow问题的第一个答案包含有关此解决方案的更多详细信息。