java - 在 Java 中检测无法访问的主机的最快方法是什么?

标签 java networking sockets

我想要最快和最准确的函数 boolean isReachable(String host, int port) 在以下条件下通过以下 JUnit 测试。超时值由 JUnit 测试本身指定,可能被视为“无法访问”。

请注意:所有答案都必须与平台无关。这意味着 InetAddress.isReachable(int timeout) 不会工作,因为它依赖于端口 7 在 Windows 上执行 ping(ICMP ping 是一个未记录的函数Windows),并且此端口在此设置中被阻止。

局域网设置:

  • 这台机器 (192.168.0.100)
  • 其他机器 (192.168.0.200)
  • 没有 机器被称为noMachine 或具有IP 192.168.0.222(始终无法访问)
  • 两台机器都在 8080 端口上运行 Apache Tomcat;所有其他端口都无法访问(包括端口 7)
  • example.com (208.77.188.166) 正在端口 80 上运行网络服务器,并且只有在 LAN 连接到互联网

有时,LAN 与 Internet 断开连接,在这种情况下,只有通过 IP 地址调用的本地计算机可以访问(所有其他计算机都无法访问;没有 DNS)。

所有测试都在 thisMachine 上运行。

@Test(timeout=1600) // ~320ms per call (should be possible to do better)
public void testLocalhost() {
    // We can always reach ourselves.
    assertTrue(isReachable("localhost", 8080));
    assertTrue(isReachable("127.0.0.1", 8080));
    assertTrue(isReachable("thisMachine", 8080)); // Even if there's no DNS!
    assertTrue(isReachable("192.168.0.100", 8080));

    assertFalse(isReachable("localhost", 80)); // Nothing on that port.
}

@Test(timeout=5500) // ~1867ms per call (should be able to do better)
public void testLAN() {
    assertTrue(isReachable("192.168.0.200", 8080)); // Always connected to the LAN.
    assertFalse(isReachable("192.168.0.222", 8080)); // No such a machine.
    assertFalse(isReachable("noMachine", 8080)); // No such machine.
}

以下测试仅在局域网与互联网断开连接时运行。

@Test(timeout=5600) // ~1867ms per call (reasonable?)
public void testNoDNS() {
    assertFalse(isReachable("otherMachine", 8080)); // No DNS.
    assertFalse(isReachable("example.com", 80)); // No DNS & no Internet.
    assertFalse(isReachable("208.77.188.166", 80)); // No Internet.
}

以下测试仅在 LAN 连接到 Internet 时运行。

@Test(timeout=5600) // ~1867ms per call (reasonable?)
public void testHaveDNS() {
    assertTrue(isReachable("otherMachine", 8080)); // DNS resolves local names.
    assertTrue(isReachable("example.com", 80)); // DNS available.
    assertTrue(isReachable("208.77.188.166", 80)); // Internet available.
}

最佳答案

首先,您需要认识到您有可能相互冲突的要求; IP 套接字不是时间确定性的。您可以检测到不可达的最快时间是在超时之后。您只能更快地检测可达性。

假设 reachability/isReachable 是您的真正目标,您应该只使用一个简单的非阻塞套接字 IO,如 Java Ping 中所示。模拟器,该示例连接到时间服务,但在 8080 上同样可以正常工作。

关于java - 在 Java 中检测无法访问的主机的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/195070/

相关文章:

sockets - 如何取消订阅 DatagramSocket MessageReceived 事件

javascript - Socket.io:接收事件触发多次

sockets - 我应该使用 IOCP 还是重叠的 WSASend/Receive?

java - 在 Joda 中将 UTC 转换为 LocalDateTime?

JavaFX 无法使用 Start 从 NetBeans 中的非 FX 项目启动

networking - 卡在从 vagrant 内的 docker 容器转发的端口上的请求

python - 只要子进程仍在运行,subprocess.Popen 后关闭套接字就会在 TIME_WAIT 中留下套接字

java - 使用简单 XML 反序列化多态类

java - 扫描非本地主机上的端口

python - 使用 asyncio 将数据从任务获取到连接