65536 個のポートごとに 200 ミリ秒が必要な場合 (最悪の場合、ファイアウォールがすべてをブロックしているため、すべてのポートでタイムアウトが発生します)、計算は非常に簡単です。13,000 秒、つまり約 3 時間必要です半分。
高速化するには、2 つの (非排他的な) オプションがあります。
操作は I/O バウンドであるため (CPU バウンドとは対照的に、つまり、膨大な計算が完了するのではなく、I/O の待機に時間を費やします)、非常に多くのスレッドを使用できます。20から始めてみてください。3時間半を2人で割るので、最大で10分くらいが目安です。これは反対側に圧力をかけることを覚えておいてください。つまり、スキャンされたホストは、「不合理」または「奇妙な」パターンで巨大なネットワーク アクティビティを検出し、スキャンを非常に簡単に検出できるようになります。
最も簡単な方法 (つまり、最小限の変更) は、ExecutorService および Future API を使用することです。
public static Future<Boolean> portIsOpen(final ExecutorService es, final String ip, final int port, final int timeout) {
return es.submit(new Callable<Boolean>() {
@Override public Boolean call() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return true;
} catch (Exception ex) {
return false;
}
}
});
}
次に、次のようなことができます。
public static void main(final String... args) {
final ExecutorService es = Executors.newFixedThreadPool(20);
final String ip = "127.0.0.1";
final int timeout = 200;
final List<Future<Boolean>> futures = new ArrayList<>();
for (int port = 1; port <= 65535; port++) {
futures.add(portIsOpen(es, ip, port, timeout));
}
es.shutdown();
int openPorts = 0;
for (final Future<Boolean> f : futures) {
if (f.get()) {
openPorts++;
}
}
System.out.println("There are " + openPorts + " open ports on host " + ip + " (probed with a timeout of " + timeout + "ms)");
}
どのポートが開いているか(上記の例のようにいくつだけでなく)を知る必要がある場合は、関数の戻り値の型を に変更する必要があります。これは、ポートとスキャンの結果を保持するFuture<SomethingElse>
場所です。SomethingElse
お気に入り:
public final class ScanResult {
private final int port;
private final boolean isOpen;
// constructor
// getters
}
次に、最初のスニペットで に変更Boolean
し、単にorの代わりにorを返しますScanResult
new ScanResult(port, true)
new ScanResult(port, false)
true
false
編集: 実際、私はちょうど気付きました: この特定のケースでは、結果 + ポートを保持するために ScanResult クラスは必要なく、どのポートが開いているかはまだわかっています。order であるListに先物を追加し、後でそれらを追加したのと同じ順序で処理するため、処理しているポートを知るために各反復でインクリメントするカウンターを持つことができます. しかし、ねえ、これは完全かつ正確であるためです. それをやろうとしないでください、それは恐ろしいです、私はこれについて考えたことをほとんど恥じています... ScanResult オブジェクトを使用すると、はるかにクリーンになります。たとえば、a を使用してスキャナーを改善します。CompletionService