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

时间:2013-01-24 01:46:48

标签: c++ sockets tcp thread-safety boost-asio

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

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

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

2 个答案:

答案 0 :(得分:4)

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

  

此操作是根据对零的或多个调用实现的   stream的async_write_some函数,被称为组合   操作即可。程序必须确保流不执行任何其他操作   写操作(例如async_write,流的async_write_some   函数或执行写入的任何其他组合操作直到   此操作完成。

read操作

  

此操作是根据对零的或多个调用实现的   stream的async_read_some函数,被称为组合   操作即可。程序必须确保流不执行任何其他操作   读取操作(例如async_read,流的async_read_some   函数,或执行读取的任何其他组合操作,直到   此操作完成。

每个插座都很出色。

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

my experience中,大多数多io_service设计都受性能和延迟要求的驱动。 HTTP Server 2 example使用io_service每个CPU进行探讨。

答案 1 :(得分:2)

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

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

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