Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在重复连接尝试时无限期地接受()块_C++_Linux_Sockets_Tcp_Netstat - Fatal编程技术网

C++ 在重复连接尝试时无限期地接受()块

C++ 在重复连接尝试时无限期地接受()块,c++,linux,sockets,tcp,netstat,C++,Linux,Sockets,Tcp,Netstat,我正在编程一个TCP服务器,我希望一次只接受一个连接,并通过重用它用于侦听的地址和端口。与服务器已启动实例的第一次连接(例如通过netcat)始终成功,但随后的连接尝试在accept()处停止,而不返回套接字描述符。我尝试了不同的队列长度,以及在前一个连接处于TIME_WAIT状态时连接,以及在它被清除后连接,但结果是相同的。netcat和netstat都报告新连接尝试成功,并报告连接已建立(无论上一个连接是否在TIME\u WAIT或过期),但我的服务器在accept()调用时卡住,因此它没有

我正在编程一个TCP服务器,我希望一次只接受一个连接,并通过重用它用于侦听的地址和端口。与服务器已启动实例的第一次连接(例如通过netcat)始终成功,但随后的连接尝试在accept()处停止,而不返回套接字描述符。我尝试了不同的队列长度,以及在前一个连接处于TIME_WAIT状态时连接,以及在它被清除后连接,但结果是相同的。netcat和netstat都报告新连接尝试成功,并报告连接已建立(无论上一个连接是否在TIME\u WAIT或过期),但我的服务器在accept()调用时卡住,因此它没有注册新连接。这种行为并不总是在第一次连接尝试时立即发生,但几乎总是在前三次连接尝试时发生

守则:


main() {
    Socket socket(10669);
    
    while (true) {
        socket.establish_connection();
        
        socket.receive(callback);
        socket.close_connection();
    }
}



void Socket::establish_connection() {
    // Creating socket file descriptor
    int server_fd = 0;
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        throw ...;
    }

    // Setting socket options
    int socket_options = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &socket_options, sizeof(socket_options))) {
        throw ...;
    }

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);

    if (bind(server_fd, (sockaddr *) &address, sizeof(address)) < 0) {
        throw ...;
    }

    if (listen(server_fd, 1) < 0) {
        throw ...;
    }

    spdlog::info("Listening for clients on port {}", port);

    // this is where it blocks at repeated connection attempts
    struct sockaddr_in client_address;
    int addrlen = sizeof(client_address);
    if ((socket = accept(server_fd, (sockaddr *) &client_address,  (socklen_t*) &addrlen)) < 0) {
        throw ...;
    }

    spdlog::info("Client connected\n");
}


void Socket::receive(SocketCallback callback) {
    while (true) {
        fd_set read_socket_fd;
        FD_ZERO(&read_socket_fd);
        FD_SET(socket, &read_socket_fd);

        int sel = select(socket+1, &read_socket_fd, NULL, NULL, NULL);

        if (sel > 0) {
            // receiving data, no problems here
        }
    }
}


void Socket::close_connection() {
    close(socket);
}
启动时(netstat):

第一次连接时(服务器):

第一次连接时(netstat):

第一次断开与客户端(服务器)的连接时:

第一次断开与客户端(netstat)的连接时:

在第二次连接尝试时,服务器不报告任何内容,因为它卡在“侦听客户端…”行上,表示在accept()处被阻止。这是netstat报告的内容(这是我在第一次断开连接后立即连接的情况,因此,当上一次连接处于TIME\u WAIT状态时):

当我完成等待时间到期,然后尝试连接时,也会发生同样的情况:

tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        1      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        0      0 localhost:10669         localhost:55134         ESTABLISHED
tcp        0      0 localhost:55134         localhost:10669         ESTABLISHED
在这两种情况下,netcat中的连接都处于活动状态,我可以自由键入,但当然没有收到任何内容;没有其他进程可以拦截连接


我知道我可能会尝试使用非阻塞accept(),但是accept()的阻塞行为非常适合我的用法,当它的行为符合预期时,所以问题是-为什么它会在重新连接时阻塞,我在这里缺少什么?

您应该创建一个服务器套接字,然后在同一套接字上重复调用
accept
。每次调用
accept
时,您似乎都在创建一个新的服务器套接字,并将旧的套接字保持打开状态

通常情况下,这是无效的,但是您使用了
SO\u REUSEPORT
来告诉操作系统您确实需要它。使用
SO\u REUSEPORT
。显然,操作系统选择将您的新连接发送到第一个套接字,然后您尝试从第二个套接字接受它,而第二个套接字没有等待新连接


若要修复此问题,请创建一个服务器套接字,然后始终从同一套接字
accept

您必须建立连接,直到在单独的函数中建立连接,并在while(true)循环外仅调用一次。然后在循环中重用套接字以接受连接。应该在while循环中调用Listen和accept。一个好的做法是为每个新连接启动一个线程,但不是一个问题,可以在单个线程中完成;现在它按预期工作。
tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
[2020-07-07 13:34:35.481] [info] Client connected
tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        0      0 localhost:54860         localhost:10669         ESTABLISHED
tcp        0      0 localhost:10669         localhost:54860         ESTABLISHED
[2020-07-07 13:35:47.903] [warning] Client disconnected
[2020-07-07 13:35:47.903] [info] Listening for clients on port 10669
tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        0      0 localhost:54860         localhost:10669         TIME_WAIT
tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        1      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        0      0 localhost:54968         localhost:10669         TIME_WAIT
tcp        0      0 localhost:54970         localhost:10669         ESTABLISHED
tcp        0      0 localhost:10669         localhost:54970         ESTABLISHED
tcp        0      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        1      0 0.0.0.0:10669           0.0.0.0:*               LISTEN
tcp        0      0 localhost:10669         localhost:55134         ESTABLISHED
tcp        0      0 localhost:55134         localhost:10669         ESTABLISHED