2017-09-07 85 views
1

我有isReachable方法InetAddress类有奇怪的行为。InetAddress isReachable方法有最小超时吗?

Method prototype是:

public boolean isReachable(int timeout) 
  • 当使用超时> 1500(毫秒),该方法等待给定的作为参数的确切时间 (如果目标IP是不可达当然.. )。
  • 当使用超时< 1500,该方法等待1000ms的最大...

的代码非常简单:

InetAddress addr = null; 
    String ip = "10.48.2.169"; 

    try { 
     addr = InetAddress.getByName(ip); 
    } catch (UnknownHostException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    Timestamp s = new Timestamp(System.currentTimeMillis()); 
    System.out.println(s + "\t Starting tests :"); 

    pingTest(addr, 100); 
    pingTest(addr, 500); 
    pingTest(addr, 1000); 
    pingTest(addr, 1500); 
    pingTest(addr, 2000); 
    pingTest(addr, 2500); 

凡pingTest被定义为:

public static void pingTest(InetAddress addr, int timeout) { 
     boolean result = false; 
     try { 
      result = addr.isReachable(timeout); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     Timestamp s = new Timestamp(System.currentTimeMillis()); 
     System.out.println(s + "\t (" + timeout + ") " + addr.toString() + " " + result); 
    } 

然后输出是:

2017-09-07 16:45:41.573 Starting tests : 
2017-09-07 16:45:42.542 (100) /10.48.2.169 false 
2017-09-07 16:45:43.542 (500) /10.48.2.169 false 
2017-09-07 16:45:44.541 (1000) /10.48.2.169 false 
2017-09-07 16:45:46.041 (1500) /10.48.2.169 false 
2017-09-07 16:45:48.041 (2000) /10.48.2.169 false 
2017-09-07 16:45:50.541 (2500) /10.48.2.169 false 

所以问题是:是否有一个最小超时InetAddress isReachable方法?(就像我怀疑1500年,但我怀疑,巨大的超时...)

或者,也许我只是做了一个巨大的错误,我仍然怀念......

告诉我,如果这还不够明确。

感谢您的帮助和想法。

+0

看看这个OpenJDK [bug报告](https://bugs.openjdk.java.net/browse/JDK-8143397),其中用户报告一个无证的最小超时(搜索术语“最小值”)。尽管这份报告几乎没有确定性,但可能有助于证实您的经验。 – MarsAtomic

回答

3

首先您应该注意到,Java支持的每个平台上INetAddress.isReachable的行为不同。我会假设你在Windows上工作。

当无证行为发生时,如果可用,应始终查看来源。对于OpenJDK,windows.net的java.net实现是here(对于Oracle JVM,它应该非常相似,但我不确定这一点)。

我们在isReachable方法实现所看到的是:

  1. 它们不依赖于平,因为他们发现在Windows ICMP协议实现太不可靠
  2. 他们的超时值传递给NET_Wait功能

所以的isReachable方法不执行ping,我们需要检查一下NET_Wait做超时联合国说明为什么不可能超过1秒的超时时间。

NET_Wait函数定义如下:src/windows/native/java/net/net_util_md.c

它包括在一个无限循环,当这些事件select函数调用期间发生这打破:

  • NET_WAIT_CONNECT在套接字文件描述符(套接字连接到远程主机)
  • 该超时结束

select函数记录在手册页中,您可以参考here。这个手册页告诉我们,超时可以“四舍五入到系统时钟粒度,并且内核调度延迟意味着阻塞时间间隔可能会超出一小部分”。

这就是为什么最小超时值不能保证的原因。另外,我认为文档没有声明任何最小的超时值,因为JVM支持的操作系统的实现有所不同。

希望这可以帮助你理解为什么。

但是,要实现想要的超时,您可以在单独的任务中测试可达性。您等待任务返回结果,或者如果您等待的时间超过了超时时间,则取消该任务或忽略其结果。