InetAddress isReachable 方法是否有最短超时时间?
Is there a minimum timeout to InetAddress isReachable method?
我在使用 InetAddress
class 的 isReachable
方法时出现了奇怪的行为。
public boolean isReachable(int timeout)
- 当使用 timeout > 1500 (ms) 时,该方法等待确切的时间
作为参数给出(当然如果目标 IP 不可访问...)。
- 当使用 timeout < 1500 时,该方法最多等待 1000 毫秒...
代码很简单:
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,但我怀疑,超时时间很长...)
或者也许我只是犯了一个我仍然想念的大错误...
如果这还不够清楚,请告诉我。
感谢您的帮助和想法。
首先你应该注意到 INetAddress.isReachable 的行为在 Java 支持的每个平台上是不一样的。我假设你在 Windows.
上工作
当发生未记录的行为时,您应该始终查看源代码(如果它们可用)。 windows 的 java.net 实现是 OpenJDK 的 here(对于 Oracle JVM 应该非常相似,但我不确定这一点)。
我们在isReachable
方法实现中看到的是:
- 他们不依赖 ping,因为他们发现 Windows ICMP 协议实施太不可靠
- 他们将超时值传递给
NET_Wait
函数
所以 isReachable 方法不执行 ping,我们需要检查 NET_Wait
对超时做了什么,以了解为什么超时不到 1 秒不可能。
这里定义了NET_Wait
函数:src/windows/native/java/net/net_util_md.c
它包含一个无限循环,当 select
函数调用期间发生这些事件时该循环会中断:
NET_WAIT_CONNECT
套接字文件描述符(套接字连接到远程主机)
- 超时结束
select
函数记录在手册页中,您可以参考 here。这个手册页告诉我们超时可以 "be rounded up to the system clock granularity, and kernel scheduling delays mean that the blocking interval may overrun by a small amount".
这就是不能保证最小超时值的原因。另外,我认为文档没有说明任何最小超时值,因为实现在 JVM 支持的操作系统上有所不同。
希望这有助于您理解原因。
但是,要实现所需的超时,您可以在单独的任务中测试可达性。您等到任务 returns 结果,或者如果您等待的时间超过超时时间,您将取消任务或忽略其结果。
我在使用 InetAddress
class 的 isReachable
方法时出现了奇怪的行为。
public boolean isReachable(int timeout)
- 当使用 timeout > 1500 (ms) 时,该方法等待确切的时间 作为参数给出(当然如果目标 IP 不可访问...)。
- 当使用 timeout < 1500 时,该方法最多等待 1000 毫秒...
代码很简单:
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,但我怀疑,超时时间很长...)
或者也许我只是犯了一个我仍然想念的大错误...
如果这还不够清楚,请告诉我。
感谢您的帮助和想法。
首先你应该注意到 INetAddress.isReachable 的行为在 Java 支持的每个平台上是不一样的。我假设你在 Windows.
上工作当发生未记录的行为时,您应该始终查看源代码(如果它们可用)。 windows 的 java.net 实现是 OpenJDK 的 here(对于 Oracle JVM 应该非常相似,但我不确定这一点)。
我们在isReachable
方法实现中看到的是:
- 他们不依赖 ping,因为他们发现 Windows ICMP 协议实施太不可靠
- 他们将超时值传递给
NET_Wait
函数
所以 isReachable 方法不执行 ping,我们需要检查 NET_Wait
对超时做了什么,以了解为什么超时不到 1 秒不可能。
这里定义了NET_Wait
函数:src/windows/native/java/net/net_util_md.c
它包含一个无限循环,当 select
函数调用期间发生这些事件时该循环会中断:
NET_WAIT_CONNECT
套接字文件描述符(套接字连接到远程主机)- 超时结束
select
函数记录在手册页中,您可以参考 here。这个手册页告诉我们超时可以 "be rounded up to the system clock granularity, and kernel scheduling delays mean that the blocking interval may overrun by a small amount".
这就是不能保证最小超时值的原因。另外,我认为文档没有说明任何最小超时值,因为实现在 JVM 支持的操作系统上有所不同。
希望这有助于您理解原因。
但是,要实现所需的超时,您可以在单独的任务中测试可达性。您等到任务 returns 结果,或者如果您等待的时间超过超时时间,您将取消任务或忽略其结果。