我目前正在研究简单的 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
映射中的线程?
最简单的解决方案可能是频繁迭代线程
(例如从另一个线程?)并加入和删除返回的线程。
请分享您的专业知识。 :)
<子>附言。是的,我知道线程池 模式。我没有在我的应用程序中使用它(无论好坏)。我正在寻找有关我当前架构的答案。
最佳答案
简单的解决方案?就 detach()
启动线程后。这意味着一旦线程终止,资源将被清理,您不需要保留 std::map<SOCKET, std::thread> threads
.
std::thread(clientHandler, client_socket).detach();
否则创建一个线程安全的 LIFO 队列,在清理期间将套接字推送给它。
然后在主循环中交替检查 accept
和那个队列,当队列中有套接字时,你会做threads.erase(socket);
对于队列中的每个套接字。
但是,如果你这样做,那么你也可以将后进先出放在另一个方向并使用线程池。
关于c++ - 客户端断开连接后处理服务器应用程序中的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31476650/