【发布时间】:2015-10-07 05:22:03
【问题描述】:
我目前正在开发简单的 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(例如来自另一个线程?)并加入和删除返回的那些。
请分享您的专业知识。 :)
PS。是的,我知道 thread pool 模式。我没有在我的应用程序中使用它(无论好坏)。我正在寻找有关我当前架构的答案。
【问题讨论】:
-
我不知道您的应用程序的规模,但众所周知,“每个客户端一个线程”服务器模型不可扩展。考虑在您的套接字上使用异步请求并忘记自己处理线程。毕竟,原始线程也被称为现代 goto(具有讽刺意味的是,您在示例中恰好使用了它)
-
确切地说,仅用于学习目的。
-
从一开始就学会正确地做事没有错。就个人而言,如果你学会了以一种方式制作服务器,我会觉得这是一种浪费,而一旦到了制作真正应用程序的时候,就必须学习一种全新的方式。当然,您仍然可以随心所欲。
-
@KABoissonneault 您所说的“套接字上的异步请求”是什么意思而忘记了自己处理线程?当当前一个没有数据要接收时,我应该只使用一个线程并转移到另一个套接字吗?
-
@KABoissonneault 你能推荐我比
gotos 更好的错误处理解决方案吗?我不想重复自己。
标签: c++ multithreading c++11 server winsock