使用多个io_service对象

时间:2013-03-19 10:28:49

标签: boost-asio

我的应用程序在其中侦听和处理来自Internet套接字和unix域套接字的消息。现在我需要将SSL添加到互联网套接字,我正在为应用程序中的所有套接字使用单个io_service对象。现在看来我需要为网络套接字和unix域套接字添加单独的io_service对象。我的应用程序中没有任何线程,我使用async_sendasync_recieve以及async_accept来处理数据和连接。请指出使用带有异步处理程序的多个io_service对象的任何示例。

2 个答案:

答案 0 :(得分:29)

这个问题存在一定程度的不确定性,好像需要多个io_service个对象。我找不到reference文档中的任何内容,或SSLUNIX Domain Sockets的概述,其中强制要求单独的io_service个对象。无论如何,这里有几个选择:


io_service

尝试使用单个io_service

如果你没有io_service对象的直接句柄,但是你有一个Boost.Asio I / O对象的句柄,比如套接字,那么关联{{1}的句柄可以通过调用socket.get_io_service()来获取对象。


io_service使用一个帖子:

如果需要多个io_service个对象,则将一个线程专用于每个io_service。这种方法用于Boost.Asio的HTTP Server 2示例。

io_service

这种方法的一个结果是它可能需要应用程序进行线程安全保证。例如,如果boost::asio::io_service service1; boost::asio::io_service service2; boost::thread_group threads; threads.create_thread(boost::bind(&boost::asio::io_service::run, &service1)); service2.run(); threads.join_all(); service1都具有调用service2的完成处理程序,则message_processor.process()需要是线程安全的或以线程安全的方式调用。< / p>


民意调查message_processor.process()

io_serviceio_service提供了非阻止替代方案。在io_service::run()将阻止所有工作完成之前,io_service::poll()将运行准备运行且不会阻塞的处理程序。这允许单个线程在多个run()对象上执行事件循环:

io_service

为了防止在没有可立即运行的处理程序时出现紧凑的循环,可能值得在睡眠中添加。请注意,此睡眠可能会在事件的整体处理中引入延迟。


将处理程序转移到单个while (!service1.stopped() && !service2.stopped()) { std::size_t ran = 0; ran += service1.poll(); ran += service2.poll(); // If no handlers ran, then sleep. if (0 == ran) { boost::this_thread::sleep_for(boost::chrono::seconds(1)); } }

一种有趣的方法是使用strand将完成处理程序转移到单个io_service。这允许每io_service个线程,同时防止需要让应用程序进行线程安全保证,因为所有完成处理程序将通过单个服务发布,其事件循环仅由单个线程处理。 / p>

io_service

这种方法确实会产生一些后果:

  • 它要求主要boost::asio::io_service service1; boost::asio::io_service service2; // strand2 will be used by service2 to post handlers to service1. boost::asio::strand strand2(service1); boost::asio::io_service::work work2(service2); socket.async_read_some(buffer, strand2.wrap(read_some_handler)); boost::thread_group threads; threads.create_thread(boost::bind(&boost::asio::io_service::run, &service1)); service2.run(); threads.join_all(); 运行的处理程序通过strand::wrap()进行包装。
  • 异步链现在运行两个io_service,从而产生了额外的复杂性。重要的是要考虑辅助io_service不再有效的情况,导致其io_service返回。

异步链通常出现在同一run()内。因此,服务永远不会用完,因为完成处理程序会在io_service上发布额外的工作。

io_service

另一方面,当使用strand将工作转移到另一个 | .------------------------------------------. V V | read_some_handler() | { | socket.async_read_some(..., read_some_handler) --' } 时,在io_service内调用包装的处理程序,使其将完成处理程序发布到service2。如果包装的处理程序是service1中唯一的工作,则service2不再有效,导致service2返回。

servce2.run()

为了解决这个问题,示例代码对 service1 service2 ==================================================== .----------------- wrapped(read_some_handler) | . V . read_some_handler NO WORK | . | . '----------------> wrapped(read_some_handler) 使用了io_service::work,以便service2保持阻止状态,直到明确告知stop()

答案 1 :(得分:1)

看起来您正在编写服务器而不是客户端。不知道这是否有帮助,但我使用ASIO与客户端的6台服务器进行通信。它使用TCP / IP SSL / TSL。您可以找到代码here

的链接

您应该只能使用一个带有多个套接字对象的io_service对象。但是,如果你确定你真的想拥有多个io_service对象,那么它应该相当容易。在我的课堂上,io_service对象是静态的。因此,只需删除static关键字以及构造函数中仅包含io_service对象的一个​​实例的逻辑。根据服务器预期的连接数量,最好使用专用于处理套接字I / O的线程池,而不是为每个新的套接字连接创建一个线程。