【发布时间】:2016-06-26 11:55:10
【问题描述】:
我正在编写一个能够处理多个并发连接的简单 tcp 套接字服务器。这个想法是主监听线程将阻塞接受和卸载套接字句柄到工作线程(在线程池中),以从那里异步处理通信。
void server::run() {
{
io_service::work work(io_service);
for (std::size_t i = 0; i < pool_size; i++)
thread_pool.push_back(std::thread([&] { io_service.run(); }));
boost::asio::io_service listener;
boost::asio::ip::tcp::acceptor acceptor(listener, ip::tcp::endpoint(ip::tcp::v4(), port));
while (listening) {
boost::asio::ip::tcp::socket socket(listener);
acceptor.accept(socket);
io_service.post([&] {callback(std::move(socket));});
}
}
for (ThreadPool::iterator it = thread_pool.begin(); it != thread_pool.end(); it++)
it->join();
}
我在堆栈上创建socket,因为我不想在while(listening) 循环内重复分配内存。
回调函数callback的原型如下:
void callback(boost::asio::socket socket);
据我了解,调用callback(std::move(socket)) 会将socket 的所有权转移给callback。但是,当我尝试从callback 内部调用socket.receive() 时,我收到Bad file descriptor 错误,所以我认为这里有问题。
如何将socket 的所有权转移给回调函数,最好不必在堆上创建套接字?
【问题讨论】:
-
错误是循环迭代结束后可能会调用您的 lambda。这意味着
socket将超出范围,并且在对它的引用上调用std::move()是未定义的。 -
我不知道在不为套接字分配空间的情况下安全地执行此操作的方法。原因是
io_service::post()copies the handler as required。您可能不安全地通过将处理程序设为类并定义复制构造函数来移动套接字来做到这一点,但请注意,这违反了复制的语义。为什么您如此不愿意在堆上分配时间或空间?在任何一种情况下,鉴于您正在创建和接受套接字,分配似乎可以忽略不计。
标签: c++ multithreading sockets boost boost-asio