我正在为Windows客户端使用Boost :: ASIO版本1.52.0。我希望能够专门处理来自服务器的所有接收消息的线程,然后是另一个专用线程来处理到服务器的所有传出消息。我现在正在为两个线程使用相同的io_service
对象。我担心的是,当调用io_service::run()
方法时,处理传出消息的线程可能会被调度来处理一些传入的消息调用,反之亦然。所以,我的问题 - 这可能吗?如果是,则使用第二个io_service
对象解决问题 - 每个线程一个?有没有更好的方法来设计它?我试图避免为读取和写入处理程序使用多个线程。
我想要确认的另一件事是 - 我已经读过,如果可以同时完成2个或更多async_reads
,则应该使用锁来单独编写代码。同样适用于async_writes
。如果an async
_ read可以与async_write
同时执行,还是应该是线程安全的,还应该使用锁吗?
最后一个问题 - 异步方法 - async_connect
,async_read
和async_write
是否可以在工作线程调用io_service
运行之前从不同的线程调用方法
答案 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个专用的非异步线程,我刚才提到您的性能会好很多。