【发布时间】:2017-11-22 14:47:44
【问题描述】:
tl;dr
如何使基于tcp::iostream 的服务器(如下面的代码)在不同的线程中接受多个连接?
我正在尝试使用 Boost.Asio 为预先存在的库实现服务器/客户端接口,沿着examples 前进。 (是的,C++11 之前的版本。请耐心等待。)
使用 tcp::iostream 的理由。
由于情况,整个服务器进程是可选的;即当使用port = 0 调用客户端时,它会将请求传递给本地Handler 实例。在其他所有情况下,它都会连接到希望在该端口号上侦听的服务器,然后服务器将请求传递给服务器进程的 Handler 实例。
(这都是严格的 127.0.0.1。服务器存在是因为多个 Handler 实例之间存在重要的共享状态,所以如果所有用户都将他们的请求发送到机器上运行的一台服务器,那么在内存和启动时间。“本地”,port = 0 选项存在,因为这样我就可以只使用一个客户端可执行文件,用于基于服务器的和本地使用。)
无论如何。有boost::asio::ip::tcp::iostream,让事情变得非常简单:
boost::asio::io_service io_service;
boost::asio::ip::tcp::endpoint endpoint( boost::asio::ip::tcp::v4(), port_ );
boost::asio::ip::tcp::acceptor acceptor( io_service, endpoint );
for (;;)
{
boost::asio::ip::tcp::iostream stream;
boost::system::error_code ec;
acceptor.accept( *stream.rdbuf(), ec );
if ( ! ec )
{
Handler( stream, stream ).run(); // <---- This is the "why"
}
else
{
throw ec.message();
}
stream.close();
}
你知道这是怎么回事。 Handler 类接受一个输入流和一个输出流。除了传递tcp::iostream,我可以传递std::cin/std::cout,或者一些指向请求文件和日志文件的std::fstream。这对我来说效果很好。
大“但是”
问题是上面的代码是严格的单线程的。由于Handler 完成的工作需要大量 时间(分钟),我需要多个工作线程。
以及所有关于“如何使 Boost.Asio 多线程”的示例和教程——例如HTTP 示例server2(使用单个io_service 对象池)和server3(使用多个线程,每个线程都调用io_service::run())——正在采用完全不同的方式(acceptor::async_accept() 处理tcp::socket 对象包含在单独的connection 对象中)。
将其归咎于我对 Boost.Asio 的整体架构的困惑,或者缺少文档,但我无法弄清楚如何将这两种方法结合起来,即有多个工作线程,每个工作线程都将其连接处理为 tcp::iostream .似乎没有办法从tcp::iostream 检索tcp::socket,也没有办法向它提供一个,此时我有点难过。
【问题讨论】:
-
您是否遇到过某个教程,我认为是在 gamedev 上?我可以帮你挖出来,但几年前我用它来做 io_service / tcp 的事情。据我回忆,io_service/run 是一种创建一堆线程的方法,它可以做任何你喜欢做的事情,但要与 asio 的各种套接字等一起使用。
-
gamedev.net/blog/950/… 找到了,正好在我的收藏夹中
-
@Carlos 再添加 1 个教程有什么帮助?
-
@DevSolar,如何为每个处理程序启动一个线程并将 iostream 或套接字传递给它?
-
@sehe:但我需要一个单独的
tcp::iostream为每个Handler,不是吗?
标签: c++ multithreading boost-asio