我的应用程序在其中侦听和处理来自Internet套接字和unix域套接字的消息。现在我需要将SSL添加到互联网套接字,我正在为应用程序中的所有套接字使用单个io_service
对象。现在看来我需要为网络套接字和unix域套接字添加单独的io_service
对象。我的应用程序中没有任何线程,我使用async_send
和async_recieve
以及async_accept
来处理数据和连接。请指出使用带有异步处理程序的多个io_service
对象的任何示例。
答案 0 :(得分:29)
这个问题存在一定程度的不确定性,好像需要多个io_service
个对象。我找不到reference文档中的任何内容,或SSL和UNIX 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_service
为io_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的线程池,而不是为每个新的套接字连接创建一个线程。