我有我的应用程序,其中侦听和处理来自 Internet 套接字和 unix 域套接字的消息。现在我需要将 SSL 添加到 Internet 套接字,我对应用程序中的所有套接字使用单个io_service
对象。现在看来我需要io_service
为网络套接字和 unix 域套接字添加单独的对象。我的应用程序中没有任何线程,我使用async_send
andasync_recieve
来async_accept
处理数据和连接。请指出任何使用io_service
带有异步处理程序的多个对象的示例。
2 回答
这个问题有一定程度的不确定性,好像io_service
需要多个对象。我在参考文档或要求单独对象的SSL和UNIX 域套接字的概述中找不到任何内容。io_service
无论如何,这里有几个选项:
单人io_service
:
尝试使用单个io_service
.
如果您没有io_service
对象的直接句柄,但您有 Boost.Asio I/O 对象(例如套接字)的句柄,则io_service
可以通过调用socket.get_io_service()
.
每使用一个线程io_service
:
如果需要多个io_service
对象,则为每个对象分配一个线程io_service
。这种方法用于 Boost.Asio 的HTTP Server 2示例。
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()
,则message_processor.process()
需要是线程安全的或以线程安全的方式调用。
民意调查io_service
:
io_service
提供非阻塞替代run()
. io_service::run()
在所有工作完成之前as 将阻塞的位置,io_service::poll()
将运行准备好运行且不会阻塞的处理程序。这允许单个线程在多个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));
}
}
为了防止在没有准备好运行的处理程序时出现繁忙的循环,可能值得在睡眠中添加。请注意,这种睡眠可能会在事件的整体处理中引入延迟。
将处理程序转移到单个io_service
:
一种有趣的方法是使用 astrand
将完成处理程序转移到单个io_service
. 这允许每个线程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();
这种方法确实有一些后果:
- 它需要打算由 main 运行的处理程序
io_service
通过strand::wrap()
. - 异步链现在通过两个
io_service
s,创建了一个额外的复杂级别。重要的是要考虑辅助io_service
节点不再有工作导致其run()
返回的情况。
异步链通常出现在同一个io_service
. 因此,服务永远不会耗尽工作,因为完成处理程序会将额外的工作发布到io_service
.
| .------------------------------------------.
V V |
read_some_handler() |
{ |
socket.async_read_some(..., read_some_handler) --'
}
另一方面,当一个 strand 用于将工作转移到另一个 strand 时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
for ,service2
因此run()
在明确告知 to 之前一直处于阻塞状态stop()
。
看起来您正在编写服务器而不是客户端。不知道这是否有帮助,但我正在使用 ASIO 从我的客户端与 6 个服务器进行通信。它使用 TCP/IP SSL/TSL。您可以在此处找到代码的链接
您应该能够将一个 io_service 对象与多个套接字对象一起使用。但是,如果您决定确实想要拥有多个 io_service 对象,那么这样做应该相当容易。在我的课堂上,io_service 对象是静态的。因此,只需删除 static 关键字以及构造函数中仅创建一个 io_service 对象实例的逻辑。根据您的服务器预期的连接数,您最好使用专用于处理套接字 I/O 的线程池,而不是为每个新的套接字连接创建一个线程。