客户端断开连接后处理服务器应用程序中的线程

Handling threads in server application after clients disconnect

我目前正在研究简单的 HTTP 服务器。我使用 C++11 中的 Winsock 和标准线程。对于每个连接(接受)的客户端,都会创建一个新线程。

std::map<SOCKET, std::thread> threads;

bool server_running = true;
while(server_running) {
    SOCKET client_socket;
    client_socket = accept(listen_socket, NULL, NULL);
    if(client_socket == INVALID_SOCKET) {
        // some error handling
    }
    threads[client_socket] = std::thread(clientHandler, client_socket);
}

clientHandler 函数大致如下所示:

while(1) {
    while(!all_data_received) {
        bytes_received = recv(client_socket, recvbuf, recvbuflen, 0);
        if(bytes_received > 0) {
            // do something
        } else {
            goto client_cleanup;
        }
    }
    // do something
}
client_cleanup: // we also get here when Connection: close was received
closesocket(client_socket);

这里我们遇到了我的问题 - 如何处理所有已结束但尚未与主线程连接且对它们的引用仍然存在于 threads 映射中的线程?

最简单的解决方案可能是经常迭代 threads(e.q。从另一个线程?)并加入和删除返回的那些。

请分享您的专业知识。 :)

PS。是的,我知道 线程池 模式。我没有在我的应用程序中使用它(无论好坏)。我正在寻找有关我当前架构的答案。

简单的解决方案?启动线程后 detach()。这意味着一旦线程终止,资源将被清理,您不需要保留 std::map<SOCKET, std::thread> threads.

std::thread(clientHandler, client_socket).detach();

否则创建一个线程安全的 LIFO 队列,在清理期间将套接字推送到它。

然后在主循环中,您交替检查 accept 和那个队列,当队列中有套接字时,您对队列中的每个套接字执行 threads.erase(socket);

但是,如果你这样做,那么你也可以将 LIFO 放在另一个方向并使用线程池。