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

标签 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 映射中的线程?

最简单的解决方案可能是频繁迭代线程(例如从另一个线程?)并加入和删除返回的线程。

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

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

最佳答案

简单的解决方案?就 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/

相关文章:

c - 竞争条件和互斥体

c++ - 使用复杂数据结构时内存泄漏( vector 数组的数组)

c++ - 将 std::vector<std::shared_ptr<T>> 转换为 std::vector<std::shared_ptr<const T>>

C++开关枚举错误

c++ - 使用 C++ 填充 TreeView 内容

c++ - 系统找不到在 Visual Studio 2012 上指定的文件

c# - WPF ViewModel在另一个线程中运行方法,报告进度,更改Button的IsEnabled并显示结果

c++ - 我对这个问题有疑问我的输出不正确

java - 我可以在 run 方法中保留 Java 线程的计数器吗?

c++ - 为什么 gcc 提示我的循环?