C++检查TCP端口

Dam*_*ian 9 c++

我已经写了一个程序C++,我需要检查TCP端口是否真的为空.

这是功能:

int checkport(char* host, char* port, int timeout)
{
    int sock;
    struct sockaddr_in sin;
    int result = 0;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(port));
    sin.sin_addr.s_addr = inet_addr(host);
    fd_set fdset;
    struct timeval tv;
    fcntl(sock, F_SETFL, O_NONBLOCK);

    int connect_result = connect(sock,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in));
    FD_ZERO(&fdset);
    FD_SET(sock, &fdset);
    tv.tv_sec = timeout;
    tv.tv_usec = 0;

    int select_result = select(sock + 1, NULL, &fdset, NULL, &tv);

    // printf("connect = [%d] | select = [%d]\n",connect_result,select_result);

    if(select_result == 1)
    {
        int so_error;
        socklen_t len = sizeof so_error;
        getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);

        // printf("so_error = [%d] \n",so_error);

        if(so_error == 0)
        {
            //Is connected
            if(hitdebug >= 4) puts("CONNECTED");
            if(hitdebug >= 2) printf("[%s:%s] OPEN\n",host,port);

            result = 1;
        }
        else
        {
            if(hitdebug >= 4) puts("CONNECT_ERROR_1");

            result = 0;

        }
    }
    else
    {
        if(hitdebug >= 4) puts("CONNECT_ERROR_2");

        result = 0;
    }

    close(sock);

    return result;
}
Run Code Online (Sandbox Code Playgroud)

问题是只检测LISTEN端口,我希望端口100%真实,甚至检测ESTABLISHED,TIME_WAIT等...

输出:

connect = [-1] | select = [1]
so_error = [111]
50983 TEST=[0]
tcp        0      0 1.2.3.4:50983       4.4.4.4:22       ESTABLISHED


connect = [-1] | select = [1]
so_error = [111]
43343 TEST=[0]
tcp        0      0 1.2.3.4:43343       4.4.4.4:22       ESTABLISHED


connect = [-1] | select = [1]
so_error = [0]
64000 TEST=[1]
tcp        0      0 1.2.3.4:64000       0.0.0.0:*               LISTEN
tcp        0      0 1.2.3.4:47669       1.2.3.4:64000       TIME_WAIT


connect = [-1] | select = [1]
so_error = [111]
54674 TEST=[0]


connect = [-1] | select = [1]
so_error = [111]
54665 TEST=[0]
Run Code Online (Sandbox Code Playgroud)

对我来说,一个空端口是当我做一个netstat -an | grep 12345 | wc -l,我看到0,甚至不是FIN_WAIT

我怎么能做到这一点?

谢谢.

n. *_* m. 15

if (the_port_is_free(port_number)) {
   /* is the port free at this point? */
}
Run Code Online (Sandbox Code Playgroud)

正确的答案是"谁知道?" 当然,它一个纳秒之前免费的,当控制在功能的某个地方the_port_is_free,但它现在是免费的吗?还有很多其他的流程,也许其中一个流程在半个纳秒之前就开始了?

这被称为竞争条件.每个程序员都应该理解这个概念.

正是因为这个问题the_port_is_free不是由您的操作系统提供的:它只会给您错误的期望,而不是正确的答案.您无法知道端口现在是否空闲,更重要的是,当您决定绑定它时,它将在一纳秒内自由.绑定端口的唯一方法是继续尝试绑定它.

这种方法适用于一大堆情况.每当有任何类型的共享资源时,通常没有任何函数可以告诉您是否可以获取它.获得它的唯一方法是继续尝试.


Use*_*ess 7

只是尝试bind使用端口进行监听 - 如果失败(SO_REUSEADDR关闭,这是默认设置),则套接字处于活动状态或处于其中一种WAIT状态.