我正在做一个简单的服务器应用,你可以有多个连接,每个连接都是一个线程。这是我想要的样子(它不起作用),有一个线程集合,每个线程实例化类连接的对象:
class connection{};
class server{
std::vector<std::thread> active_connections;
public:
void listen() {active_connections.push_back(std::thread(connection));}
};
我一直在寻找解决方案,但我能找到的最好的是一些成员函数线程。当我测试它时,解决方案变得非常错误,例如:
class connection{};
class server{
std::vector<std::thread> active_connections;
public:
void new_connection() { ... }
void listen() {
active_connections.push_back(std::thread(&server::new_connection,this)); }
};
消息是:错误:使用已删除的函数'std :: thread :: thread(const std :: thread&amp;)。 这是否意味着std :: thread类想要复制服务器类?我不太了解C ++,所以请不要火焰,我只是问。
谢谢!
编辑:
这就是发生这种情况的地方:
void server::do_listen()
{
int addr_size = sizeof(sockaddr_in);
sockaddr_in client_sock;
connection_info cn_info;
while(true)
{
int csock;
if((csock = accept(server_sock, (sockaddr*)&client_sock, (socklen_t*)&addr_size)) != -1)
{
printf("Incomming connection from %s.\n", inet_ntoa(client_sock.sin_addr));
memset(&cn_info,0, sizeof(connection_info));
cn_info.sock_addr = client_sock;
cn_info.sock = csock;
std::thread thr(&server::new_connection, *this, cn_info);
thr.join();
}
}
}
到目前为止。 server::new_connection()
仍为空。
答案 0 :(得分:3)
问题在于:
std::thread thr(&server::new_connection, *this, cn_info);
^
您正在绑定服务器对象的副本;这是不可复制的,因为它包含(一个容器)不可复制的thread
个对象。相反,绑定一个指针:
std::thread thr(&server::new_connection, this, cn_info);
有些人可能会发现lambda更具可读性;这会按值捕获this
指针和cn_info
:
std::thread thr([=]{new_connection(cn_info);});
正如评论员所提到的,你可以通过绑定reference wrapper来混淆解决方案:
std::thread thr(&server::new_connection, std::ref(*this), cn_info);
但我更愿意在可能的情况下删除而不是添加复杂性。
答案 1 :(得分:2)
这是否意味着std :: thread类想要复制服务器类?
不,这意味着std::thread
的副本会在某个地方制作,但NonCopyable中的std::thread
被禁止(请注意列表中的thread(const thread&) = delete;
建设者)。
您应该删除执行thread
副本的任何代码。您发布的那个没有执行此类复制。
在场景后面制作副本的示例&#34;将是线程变量向量中的push_back
,即:
std::thread myThread;
myVector.push_back(myThread);
在您的代码中:
active_connections.push_back(std::thread(&server::new_connection,this));
当你正在推回一个临时的时候,它不会被复制但会被移入矢量。
答案 2 :(得分:0)
更多设计问题给你作者:
您为一个连接创建一个线程。如果你有十个连接,你有十个线程。但是如果你想要处理10000个连接,你会怎么做?我不确定您的操作系统是否喜欢它。
一种更好的连接处理方法 - 仅在我看来 - 如果你只有N个线程来处理你的网络连接。如果你的电脑有例如六个核心,你可以只为网络的东西花一个,两个或更多的线程。所以你有一个特定大小的线程池。
proactor模式对你来说很有意思:
http://en.wikipedia.org/wiki/Proactor_pattern
如果您正在寻找可以处理此类事情的库,您可以查看即将推出的名为Boost.Asynchronous的C ++ Boost库:
https://github.com/henry-ch/asynchronous
这个库仍在开发中,但非常好。我用库制作了一些简单的客户端/服务器应用程序。