使用Java扫描端口的最快方法

我做了一个非常简单的端口扫描程序,但是它运行太慢,因此我正在寻找一种使它扫描速度更快的方法。这是我的代码:

public boolean portIsOpen(String ip, int port, int timeout) {

try {

Socket socket = new Socket();

socket.connect(new InetSocketAddress(ip, port), timeout);

socket.close();

return true;

} catch (Exception ex) {

return false;

}

}

此代码测试是否在特定ip上打开了特定端口。对于超时,我使用了最小值,200因为当我降低该值时,它没有足够的时间来测试端口。

回答:

如果您需要为65536个端口中的每个端口花费200毫秒的时间(在最坏的情况下,防火墙会阻止所有内容,从而使每个端口都超时),那么计算就非常简单:您需要13,000秒,或者大约3个小时,一半。

您有2个(非专有)选项可以使其更快:

  • 减少您的超时
  • 并行化您的代码

由于操作是受I / O约束的(与CPU约束相反,也就是说,您花时间等待I / O,而不是花一些时间完成大量计算),因此

。尝试从20开始。它们会将其中的3小时半分开,

。只需记住,这将给另一侧带来压力,即,被扫描的主机将看到具有“不合理”或“奇怪”模式的大量网络活动,从而使扫描非常容易检测。

最简单的方法(即更改最少)是使用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

}

然后,在第一个代码段中更改BooleanScanResult,然后返回new ScanResult(port, true)new

ScanResult(port, false)而不是just truefalse

编辑:实际上,我只是注意到:在这种特殊情况下,您不需要ScanResult类来保存结果+端口,并且仍然知道哪个端口是打开的。既然你添加期货一个

,这是 ,并且,以后,你

,你可以有一个计数器,你会在每次迭代增量知道你正在处理哪个端口。但是,嘿,这只是为了完整和精确。

,这太可怕了,我为自己想到的事情感到mostly愧…

,代码更易于阅读和维护,并允许您以后使用,例如,使用a CompletionService改进扫描仪。

以上是 使用Java扫描端口的最快方法 的全部内容, 来源链接: utcz.com/qa/406808.html

回到顶部