2013-01-24 65 views
3

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

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

最后一个问题 - 可以在异步方法 - async_connectasync_readasync_write全部由工作线程之前不同的线程调用已调用io_service run方法?

回答

4

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

此操作在零或多次调用 流的async_write_some功能上实现,被称为一个组成 操作。该程序必须确保流不执行其他 写操作(如async_write,该流的async_write_some 功能,或者执行写操作的任何其它组成的操作)此操作完成直到 。

read操作

此操作中的零级或更多的呼叫方面实现为将 流的async_read_some功能,并且已知为组成 操作。该程序必须确保该流不会执行其他读取操作(如async_read,流的async_read_some 函数或执行读取的任何其他组合操作),直到 此操作完成。

对于每个插座都非常出色。

使用所有async_write()操作所有async_read()操作的io_service和另一io_service因为单个插座被传递作为在constructor一个参数一个io_service服务是不可能的。

my experience大多数多服务设计是由性能和延迟要求驱动的。 HTTP Server 2 example以每个CPU io_service为例进行探讨。

+0

感谢您澄清每个套接字只使用一个io_service对象。我写的客户可能需要最终使用优先处理程序。我已经找到了这个例子。我只是希望我可以避免必须实施,因为它似乎有点牵扯。我希望通过将线程专用于传入消息,并将另一个线程用于传出消息,我可以保持传出消息的处理非常灵敏。猜猜我会用2个线程尝试它,实现链或锁定,并希望最好。 –

2

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

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

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