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

时间:2008-10-12 03:53:09

标签: java networking sockets

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

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

LAN设置:

  • thisMachine192.168.0.100
  • otherMachine192.168.0.200
  • 没有计算机被称为noMachine或具有IP 192.168.0.222(始终无法访问)
  • 两台机器都在端口8080上运行Apache Tomcat;所有其他端口都无法访问(包括端口7
  • example.com208.77.188.166)正在端口80上运行网络服务器,只有在LAN连接到Internet时才能访问

有时,局域网与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.
}

以下测试仅在LAN与Internet 断开连接时运行。

@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.
}

6 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:1)

如果要测试是否可以连接到Web服务器,还可以根据主机名和端口号创建URL,并使用它创建URLConnection检查结果( connect method的例外情况应该告诉您网络服务器是否可以访问。

答案 2 :(得分:0)

我最近的解决方案取决于在执行连接时使用TimedSocketsource code)超时3000毫秒。

时序:

  • 1406ms:testLocalHost()
  • 5280ms:testLAN()

甚至无法让它们正常工作:

  • testNoDNS()
  • testHaveDNS()

答案 3 :(得分:0)

不确定这是多么实用。

如何做相当于traceroute(windows上的tracert),一旦取得成功,你就可以继续了。

在企业网络中,我看到ICMP(ping)被管理员阻止但通常,tracert仍然有效。如果你能找到一个快速的方法来做tracert的工作,那应该可以解决这个问题吗?

祝你好运!

答案 4 :(得分:0)

如果您需要在非常短的时间内对大量主机执行此操作,我会考虑使用fping之类的工具代替shell来执行它并解析输出回来。 fping一次运行大量并行查询,理论上你可以在一分钟内检查几千个主机(我认为限制是4096?)

答案 5 :(得分:0)

主机可用性的速率确定步骤不在您自己的代码中,而是在netlag中。您必须等待主机响应,这可能需要一些时间。如果您的程序在等待响应时阻塞,则可能是一个问题。我通过创建每个主机作为对象来解决这个问题,每个主机都有自己的线程方法来检查可用性。在我自己的情况下,我有40个主机,我跟踪。我的主程序每20秒循环一次由40个机器对象组成的数组,在每个机器上调用适当的方法来检查可用性。由于每个机器对象产生自己的线程来执行此操作,因此所有40台机器同时被查询,并且每个机器的响应时间(最多500毫秒)都不是问题。

相关问题