Boost::ASIO - 如何专用 2 个线程来处理接收和发送消息

Posted

技术标签:

【中文标题】Boost::ASIO - 如何专用 2 个线程来处理接收和发送消息【英文标题】:Boost::ASIO - how to dedicate 2 threads to handle receiving and sending messages 【发布时间】:2013-01-24 01:46:48 【问题描述】:

我正在为 Windows 客户端使用 Boost::ASIO 版本 1.52.0。我希望能够专用一个线程来处理从服务器接收的所有消息,然后另一个专用线程来处理所有传出到服务器的消息。我现在对两个线程都使用相同的 io_service 对象。我担心的是,当调用io_service::run() 方法时,处理传出消息的线程可能会被安排处理一些传入消息调用,反之亦然。所以,我的问题 - 这可能吗?如果是,那么使用第二个io_service 对象是否可以解决问题——每个线程一个对象?有没有更好的方法来设计这个?我试图避免对读写处理程序使用多个线程。

我想确认的另一件事是 - 我已经读过,如果可以同时完成 2 个或多个 async_reads,则应该使用锁来单线程代码。同样适用于async_writes。如果an async_read 可以与async_write 同时执行,是否也应该使用锁,还是应该是线程安全的?

最后一个问题 - 在工作线程调用 io_service 运行方法之前,异步方法 - async_connectasync_readasync_write 都可以从不同的线程调用吗?

【问题讨论】:

【参考方案1】:

您应该使用单个io_service,但是用于调用io_service::run() 的许多线程也可以为io_service 拥有的异步操作调用处理程序。如果这些处理程序访问共享数据结构,您将需要使用strand 来确保独占访问。您还需要确保最多进行一次write 操作

这个操作是在零次或多次调用 流的async_write_some 函数,被称为 composed 操作。程序必须确保流不执行其他 写操作(如async_write,流的async_write_some 函数或任何其他执行写入的组合操作)直到 此操作完成。

和read操作

这个操作是在零次或多次调用 流的async_read_some 函数,被称为 composed 操作。程序必须确保流不执行其他 读操作(如async_read,流的async_read_some 函数或任何其他执行读取的组合操作)直到 此操作完成。

对于每个套接字都很出色。

不可能对所有async_write() 操作使用io_service,对所有async_read() 操作使用另一个io_service,因为单个套接字由一个io_service 提供服务,该io_service 作为@987654323 中的参数传入@。

在my experience 中,大多数 mult-io_service 设计都是由性能和延迟要求驱动的。 HTTP Server 2 example 使用每个 CPU 的 io_service 来探索这一点。

【讨论】:

感谢您对每个套接字仅使用一个 io_service 对象的说明。我正在编写的客户端可能最终需要使用优先处理程序。我已经找到了这个例子。我只是希望我可以避免实施它,因为它似乎有点涉及。我希望通过将一个线程专用于传入消息,并将另一个线程用于传出消息,我可以保持传出消息的处理非常灵敏。我想我会用 2 个线程尝试它,实现链或锁定,并希望最好。【参考方案2】:

当您没有多个对象(即套接字)可供操作时,这是 ASIO 和 IOCP 等异步库的失败之一。就像单个 UDP 套接字向许多不同的端点发送和接收许多数据包的常见情况一样。

在这种情况下,有一个专门的线程只是在读取时阻塞并快速将数据放入队列中,而一个专门的线程在写入时阻塞比异步任何东西都要高效得多。通过这种方式,您应该能够在现代硬件上每秒获得超过 100K 的数据包。如果您可以使用 sendmmsg 或 recvmmsg 类型的函数,则可以通过避免操作系统调用开销来获得更高的数字。它们允许您将消息捆绑在一起,但最后我检查了它不在 ASIO 中,并且需要您自己的代码。

在您的示例应用程序中,因为一次只有一个 READ 或 WRITE 处理程序处于活动状态,因此两个线程应该只执行一个或另一个,因此我相信您可以避免那里需要 strand。但是,如果您在我刚才提到的设置中改用 2 个专用的非异步线程,您的性能会好很多。

【讨论】:

以上是关于Boost::ASIO - 如何专用 2 个线程来处理接收和发送消息的主要内容,如果未能解决你的问题,请参考以下文章

boost::asio io_service 和 std::containers 的线程安全

boost::asio::socket 线程安全

Boost.Asio 异步 TCP 客户端和多线程

多线程中boost asio中的随机EOF

Boost::asio - 如何中断阻塞的 tcp 服务器线程?

boost::asio io_service 停止特定线程