tl;dr
如何使基于tcp::iostream
的服务器(如下面的代码)在单独的线程中接受多个连接?
我正在尝试使用Boost.Asio实现一个预先存在的库的服务器/客户端接口,通过示例摸索前进。(是的,这是C++11之前的版本。请耐心等待。)
选择tcp::iostream的原因:
由于情况特殊,整个服务器过程是可选的;也就是说,当客户端调用
port=0
时,它将请求传递给本地Handler
实例。在其他所有情况下,它会连接到希望侦听该端口号的服务器,并将请求传递给服务器进程的Handler
实例。(这都是严格的127.0.0.1。服务器存在是因为多个
Handler
实例之间存在重要的共享状态,因此如果所有用户都向运行在计算机上的一个服务器发送请求,那么对于内存和启动时间来说,这将更加容易。 "local",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::fstream
,或者传递 std::cin
/ std::cout
。这对我非常有效。但是问题在于上面的代码严格单线程。由于
Handler
执行的任务需要花费很长时间(几分钟),我需要多个工作线程。
所有关于“如何使Boost.Asio支持多线程”的示例和教程 -- 例如HTTP示例server2(使用独立io_service
对象池)和server3(使用多个线程,每个线程调用io_service::run()
)-- 都采用了一个完全不同的方法(通过在单独的connection
对象中包含一个tcp::socket
对象,使acceptor::async_accept()
工作)。
要么因为我对Boost.Asio的总体架构感到困惑,要么因为缺乏文档,但我无法弄清如何结合这两种方法,即拥有多个工作线程,每个线程处理其连接作为tcp::iostream
。似乎没有办法从tcp::iostream
中检索tcp::socket
,也没有给它提供tcp::socket
的方法,这时我有点困惑。
tcp::iostream
的理由是什么?我非常喜欢这个事实,即我可以有一个Handler
类来处理所有的操作,无论是基于文件、cin
/cout
还是网络。此外,“异步_*()` 调用和回调(我认为您所说的是“传统的 asio 方法”)的链接感觉很麻烦。 - DevSolar