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

时间:2015-07-17 13:11:55

标签: c++ multithreading c++11 server winsock

我目前正在开发简单的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。是的,我知道线程池模式。我没有在我的应用程序中使用它(无论好坏)。我正在寻找有关我目前架构​​的答案。

1 个答案:

答案 0 :(得分:2)

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

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

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

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

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