我对isReachable
类的InetAddress
方法有一种奇怪的行为。
public boolean isReachable(int timeout)
代码非常简单:
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 :(得分:4)
首先,您应该注意到Java支持的每个平台上INetAddress.isReachable的行为都不相同。我假设您在Windows上工作。
当未记录的行为发生时,您应始终查看源是否可用。对于OpenJDK,Windows的java.net实现是here(它应该与Oracle JVM非常相似,但我不确定这一点。)
我们在isReachable
方法实现中看到的是:
NET_Wait
函数所以 isReachable方法不会执行ping ,我们需要检查NET_Wait
对超时的处理方式,以了解为什么不到1秒的超时时间为&#39可能。
此处定义了NET_Wait
函数:src/windows/native/java/net/net_util_md.c
它包含一个无限循环,在select
函数调用期间发生这些事件时会中断:
NET_WAIT_CONNECT
关于套接字文件描述符(套接字连接到远程主机) select
功能记录在您可以咨询的手册页here中。该手册页告诉我们,超时可以被四舍五入到系统时钟粒度,并且内核调度延迟意味着阻塞间隔可能会超出一小部分"。
这就是为什么不能保证最小超时值。此外,我认为文档没有说明任何最小超时值,因为实现在JVM支持的操作系统上有所不同。
希望这可以帮助您理解原因。
但是,要实现所需的超时,您可以在单独的任务中测试可达性。您等到任务返回结果,或者等待超过超时时取消任务或忽略其结果。