提高端口扫描器的性能
所以我今天早上在C++上制作了一个端口扫描器,它似乎能够正常工作,只是有一个令人讨厌的问题 - 每当我用它在网络上扫描IP时,它都需要10每个端口-20秒。提高端口扫描器的性能
好像connect()方法是这么长时间。
现在除了多线程之外,我敢肯定会加快这个过程但不会太多,我怎么能让这个更快?这里是扫描的代码段:
for (i = 0; i < a_size(port_no); i++)
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
target.sin_family = AF_INET;
target.sin_port = htons(port_no[i]);
target.sin_addr.s_addr = inet_addr(argv[1]);
if (connect(sock, (SOCKADDR *)&target, sizeof(target)) != SOCKET_ERROR)
cout << "Port: " << port_no[i] << " - open" << endl;
else
cout << "Port: " << port_no[i] << " - closed" << endl;
closesocket(sock);
}
如果你需要更多的让我知道。
另外,我正在使用winsock2.h文件。是不是因为这么慢?
当你调用connect(2)
,操作系统通过发送SYN
包到其他同行发起three-way handshake。如果没有收到响应,它会稍微等待并发送一些更多SYN
数据包。如果在给定超时后没有收到响应,则操作失败,并且connect(2)
返回,错误代码为ETIMEODOUT
。
通常情况下,如果一个对等设备启动但不接受给定端口上的TCP连接,它将回复任何带有RST
数据包的SYN
数据包。这将导致connect(2)
以更快的速度(一个网络往返时间)发生故障,并显示错误ECONNREFUSED
。但是,如果对等端设置了防火墙,它将忽略您的SYN
数据包,并且不会发送这些数据包,这将导致connect(2)
花费很长时间才会失败。
因此,如果您希望避免等待每个端口的超时,您需要并行执行多个连接。您可以执行此多线程(每个线程调用一个同步connect(2)
),但由于线程占用大量资源,因此不能很好地扩展。
更好的方法是使用非阻塞套接字。要使插座无阻塞,请拨打fcntl(2)
,并输入F_SETFL
选项和O_NONBLOCK
选项。然后,connect(2)
将立即返回EWOULDBLOCK
或EAGAIN
,此时您可以使用select(2)
或poll(2)
和朋友一次监视大量套接字。
当我将F_SETFL和O_NONBLOCK传递给fcntl()时,我的编译器抛出一个错误,表示它们没有被声明。我似乎找不到任何需要任何人声明它们的文档或示例... 我在网上找到的所有示例都是按照原样传递它们的。 fcntl本身没有任何编译问题 – user1324674 2013-05-08 19:05:53
@ user1324674:确保你包含'#include
我想我没有提到我在这个项目中使用Windows。 显然fcntl在这里不起作用 – user1324674 2013-05-13 16:57:16
我想出了一个适用于Windows的解决方案。首先我说:
u_long on = 1;
timeval tv = {0, 1000}; //timeout value in microseconds
fd_set fds;
FD_ZERO(&fds);
然后我改变了这种代码看起来像这样:
for (i = 0; i < a_size(port_no); i++)
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
FD_SET(sock, &fds);
ioctlsocket(sock, FIONBIO, &on);
target.sin_family = AF_INET;
target.sin_port = htons(port_no[i]);
target.sin_addr.s_addr = inet_addr(argv[1]);
connect(sock, (SOCKADDR *)&target, sizeof(target));
err = select(sock, &fds, &fds, &fds, &tv);
if (err != SOCKET_ERROR && err != 0)
cout << "Port: " << port_no[i] << " - open" << endl;
else
cout << "Port: " << port_no[i] << " - closed" << endl;
closesocket(sock);
}
,似乎现在快得多的功能!我会做一些工作来优化它&清理它一下,但是感谢所有你输入的每个人的回应! :)
可能会有某种超时丢失。 – Drise 2013-05-06 22:11:11
如果你想减少等待连接的时间,使它成为一个非阻塞套接字并在'connect'后调用'select'。 – 2013-05-06 22:11:54
@CaptainObvlious,我其实也觉得我在某处在线阅读。今天晚些时候,当我有机会的时候,我会再试一次。谢谢! – user1324674 2013-05-06 22:12:59