12

boolean isReachable(String host, int port)以下の条件で以下のJUnitテストに合格する最速かつ最も正確な関数が欲しいです。タイムアウト値はJUnitテスト自体によって指定され、「到達不能」と見なされる場合があります。

注意:すべての回答はプラットフォームに依存しない必要があります。これは、 Windowsでpingを実行するためInetAddress.isReachable(int timeout)にポートに依存しているため7(ICMP pingはWindowsでは文書化されていない機能です)、このセットアップではこのポートがブロックされているため、機能しないことを意味します。

LANセットアップ:

  • thisMachine192.168.0.100
  • otherMachine192.168.0.200
  • マシンが呼び出されnoMachineていないか、IPがありません192.168.0.222(常に到達不能)
  • 両方のマシンがポートでApacheTomcatを実行しています8080。他のすべてのポートに到達できません(ポートを含む7
  • example.com208.77.188.166)はポートでWebサーバーを実行しており80、LANがインターネットに接続されている場合にのみ到達可能です

場合によっては、LANがインターネットから切断されます。その場合、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がインターネットから切断されている場合にのみ実行されます。

@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がインターネットに接続されている場合にのみ実行されます。

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

6 に答える 6

6

まず、競合する可能性のある要件があることを認識する必要があります。IP ソケットは時間決定論的ではありません。到達不能を検出できる最も速いのは、経過したタイムアウトの後です。到達可能性をより迅速に検出することしかできません。

到達可能性/isReachable が実際の目的であると仮定すると、 Java Pingシミュレーターに示されているように、単純なノンブロッキング ソケット IO を使用する必要があります。例はタイム サービスに接続しますが、8080 でも同様に機能します。

于 2008-10-14T10:24:20.733 に答える
1

Web サーバーに接続できるかどうかをテストする場合は、ホスト名とポート番号に基づいて URL を作成し、それを使用して URLConnection を作成しconnectメソッドの結果 (例外を含む) をチェックして、Web サーバーに到達可能です。

于 2008-10-14T07:08:40.177 に答える
0

私の最新の解決策は、接続の実行中に3000msのタイムアウトでTimedSocketソースコード)を使用することに依存しています。

タイミング:

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

これらを正しく機能させることさえできません:

  • testNoDNS()
  • testHaveDNS()
于 2008-10-12T03:54:20.710 に答える
0

これがどれほど実用的かわからない。

traceroute(Windowsのtracert)と同等の処理を実行して、成功したら続行できます。

企業ネットワークでは、管理者によってICMP(ping)がブロックされているのを見てきましたが、通常、tracertは引き続き機能します。tracertが行うことをすばやく実行する方法を理解できれば、それでうまくいくはずです。

幸運を!

于 2008-10-12T04:08:23.567 に答える
0

ホストの可用性の律速段階は、独自のコード内ではなく、ネットラグ内にあります。ホストが応答するのを待つ必要があり、これには時間がかかる場合があります。応答を待っている間にプログラムがブロックする場合は、問題が発生している可能性があります。これを回避するには、各ホストをオブジェクトとして作成し、それぞれに可用性を確認するための独自のスレッドメソッドを使用します。私自身の状況では、追跡しているホストが40人います。私のメインプログラムは、20秒ごとに40個のマシンオブジェクトの配列をループし、それぞれで適切なメソッドを呼び出して可用性を確認します。各マシンオブジェクトはこれを行うために独自のスレッドを生成するため、40台のマシンすべてが同時に問い合わせられ、それぞれの(最大500ms)応答時間は問題になりません。

于 2011-04-29T04:23:07.747 に答える
0

非常に多くのホストで非常に短時間にこれを行う必要がある場合は、代わりにfpingなどのツールを使用することを検討します。シェルを実行して実行し、戻ってきたときに出力を解析します。fping は一度に多数の並列クエリを実行するため、理論的には 1 分間に数千のホストをチェックできます (制限は 4096 だと思いますか?)。

于 2008-10-15T16:52:48.280 に答える