Unix TCP端口扫描程序

Kar*_*udi 0 c unix tcp port-scanning

我有一个TCP端口扫描程序,它扫描给定IP上的所有开放端口,并仅返回打开的端口和符号上的服务名称.为此,我创建一个套接字,将其设置为非阻塞模式,并select()在端口上如果超时则表示端口已关闭,否则打开.问题是我的select()总是超时,即使我尝试扫描开放端口.我希望有人指出我的错误,我的逻辑是不是很糟糕?

#include <stdlib.h>
#include <iostream>
#include <cstdio>
#include <string.h>
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/time.h>
#include <errno.h>

using namespace std;
fd_set    working_set;
hostent *he;
char* protoc [2] = { "tcp","udpn" };
int port;
struct sockaddr_in servaddr;
int sendfd;
servent *srvport;
void set_nonblock(int socket) {
    int flags;
    flags = fcntl(socket,F_GETFL,0);
    assert(flags != -1);
    fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
void set_block(int socket) {
    int flags;
    flags = fcntl(socket,F_GETFL,0);
    assert(flags != -1);
    fcntl(socket, F_SETFL, flags | ~O_NONBLOCK);
}

int main( int argc, char* argv[] )
{

    struct timeval  timeout;
    timeout.tv_sec  = 1;
    timeout.tv_usec = 0;
    char* host = argv[1];
    char* pro = argv[2];
    int portlow  = atoi(argv[3]);
    int porthigh = atoi(argv[4]);

    fprintf(stderr, "n Scanning host=%s, protocol=%s, ports: %d -> %d   \n",
            host, pro, portlow, porthigh);

    if(strcmp(pro, protoc[0])==0)
        pro = protoc[0];
    else if (strcmp(pro, protoc[1])==0)
        pro = protoc[1];
    else
    {
        herror("n specify valid protocol - tcp or udpn");
        exit(-1);
    }


    if((he = gethostbyname(argv[1])) == NULL)
    {
        herror("n *** gethostbyname() failed ***n");
        exit(-1);
    }
    /*In case TCP protocol is selected for scan, app opens streaming socket

for every port to be scanned, tries to connect to it, and if successful

it displays information about service using struct servent.
*/

    if(strcmp(pro, protoc[0])==0) // tcp scan
    {
        for(port = portlow; port <= porthigh; port++)
        {
            // open stream socket
            if((sendfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            {
                perror("*** socket(,SOCK_STREAM,) failed ***n");
                exit(-1);
            }
            set_nonblock(sendfd);
            bzero(&servaddr, sizeof(servaddr));

            servaddr.sin_family = AF_INET;
            servaddr.sin_port = htons(port);
            servaddr.sin_addr = *((struct in_addr *)he->h_addr);
            int res = connect(sendfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
int ser;
            if (res < 0) {
                 if (errno == EINPROGRESS) {
                    timeout.tv_sec = 0;
                    timeout.tv_usec = 10;
                    FD_SET(sendfd, &working_set);

                    if ((ser=select(sendfd+1, NULL, &working_set, NULL, &timeout)) > 0) {
                          srvport = getservbyport(htons(port), protoc[0]);

                    }
                    else {
                       fprintf(stderr, "Timeout or error() %d\n",ser);
                       perror("select(): ");

                    }
                 }
                 else {
                    fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
                 }
                 if(srvport != NULL)
                     printf("tport %d: %sn   \n ", port, srvport->s_name);
                 else if (ser=0)
                   close(sendfd);
                 fflush(stdout);
              }

            //set_block(sendfd);
        }//end of for()
    }
}
Run Code Online (Sandbox Code Playgroud)

unw*_*ind 5

这是相当多的代码.我没有运行它.但是,这个:

if (ser=(select(sendfd, NULL, &working_set, NULL, &timeout)) > 0) {
Run Code Online (Sandbox Code Playgroud)

是错的.第一个参数select()是"三组中任何一组中编号最大的文件描述符加1"(参见手册页).

另外,你应该像这样括号:

if ((ser = select(...)) > 0) {
Run Code Online (Sandbox Code Playgroud)

因为现在你将>操作符的结果ser赋给变量,这可能不是你所期望的.