改善端口扫描仪性能

时间:2013-05-06 22:06:04

标签: c++ windows winsock2

所以今天早上我用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文件。是因为它这么慢吗?

3 个答案:

答案 0 :(得分:2)

当您呼叫connect(2)时,操作系统会通过向另一个对等方发送SYN数据包来启动three-way handshake。如果没有收到响应,它会稍微等待并发送一些SYN个数据包。如果在给定超时后仍未收到任何响应,则操作将失败,connect(2)将返回错误代码ETIMEODOUT

通常,如果对等体已启动但未接受给定端口上的TCP连接,则它将回复具有SYN数据包的任何RST数据包。这将导致connect(2)失败得更快(一个网络往返时间),错误为ECONNREFUSED。但是,如果对等方设置了防火墙,它将忽略您的SYN数据包,并且不会发送那些RST数据包,这将导致connect(2)花费很长时间失败。

因此,如果您想避免等待每个端口的超时,则需要并行执行多个连接。您可以执行此多线程(每个线程一次同步connect(2)调用),但由于线程占用了大量资源,因此无法很好地扩展。

更好的方法是使用非阻塞套接字。要使套接字无阻塞,请使用F_SETFL选项和O_NONBLOCK选项调用fcntl(2)。然后,connect(2)将立即返回EWOULDBLOCKEAGAIN,此时您可以使用select(2)poll(2)和朋友来监控​​大量的一次插座。

答案 1 :(得分:1)

尝试创建一个非阻塞套接字数组,以便一次排队一堆连接尝试。

了解here

答案 2 :(得分:0)

我找到了适用于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);
}

现在看起来功能要快得多!我会做一些工作来优化它&amp;清理一下,但感谢所有回复的人! :)