扫描开放端口

时间:2015-09-26 12:48:08

标签: sockets network-programming

我尝试使用以下代码片段扫描我的IP上的开放端口,完成时间超过20分钟,但我需要在不到一分钟的时间内完成任务。如果有人能给我一个想法我很感激。谢谢你提前。

- (void)scanForOpenPorts
{
    struct hostent *host;
    int err, i, sock;
    char hostname[100] = "192.168.1.17";
    struct sockaddr_in sa;

    //Initialise the sockaddr_in structure
    memcpy((char*)&sa , "" , sizeof sa);
    sa.sin_family = AF_INET;

    //direct ip address, use it
    if(isdigit(hostname[0]))
    {
        printf("Doing inet_addr...");
        sa.sin_addr.s_addr = inet_addr(hostname);
        printf("Done\n");
    }
    //Resolve hostname to ip address
    else if( (host = gethostbyname(hostname)) != 0)
    {
        printf("Doing gethostbyname...");
        memcpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);
        printf("Done\n");
    }
    else
    {
        herror(hostname);
        exit(2);
    }

    //Start the port scan loop
    printf("Starting the portscan loop : \n");

    NSLog(@"Start Time: %@", [NSDate date]);

    for(i = 0; i <= 65536; i++)
    {
        //Fill in the port number
        sa.sin_port = htons(i);
        //Create a socket of type internet
        sock = socket(AF_INET , SOCK_STREAM , 0);

        //Check whether socket created fine or not
        if(sock < 0)
        {
            perror("\nSocket");
            exit(1);
        }
        //Connect using that socket and sockaddr structure
        err = connect(sock , (struct sockaddr*)&sa , sizeof sa);

        //not connected
        if( err < 0 )
        {
            //printf("%s %-5d %s\r" , hostname , i, strerror(errno));
            fflush(stdout);
        }
        //connected
        else
        {
            printf("%-5d open\n",  i);
        }

        close(sock);
    }

    NSLog(@"End Time: %@", [NSDate date]);

    printf("\r");
    fflush(stdout);
}

1 个答案:

答案 0 :(得分:0)

您正在阻塞模式下使用套接字,并在connect()上以串行方式一次测试一个端口而没有超时。因此,扫描如此大范围的端口当然需要很长时间。您需要并行化代码,以便可以同时连接到多个端口,从而减少扫描端口范围所需的时间。

使用select()poll()或等效的非阻塞套接字为connect()提供超时(大多数平台不提供指定connect()超时的方法在阻塞模式下,所以你受到套接字堆栈内部超时的限制。)

让多个套接字同时连接到不同的端口,无论是在单个工作线程中,还是至少在select() / poll()循环中。

在任何给定时间运行有限数量的连接,以免压倒设备或网络。开始几个连接开始。当任何给定套接字连接到其当前端口时,让该线程/插槽选择下一个可用端口,如果需要,关闭+重新创建其套接字,然后重试。根据需要重复操作,直到端口范围用完为止。

每次connect()失败而没有超时,您可以为下一个connect()重复使用相同的套接字,您不需要close()它。但是,如果connect()成功,或者超时失败,则必须close()该套接字并为下一个connect()创建一个新套接字。