8

boost::asio::io_service用来管理一些异步 TCP 通信。这意味着我创建一个boost::asio::ip::tcp::socket并给予io_service它。当我开始通信时,它的示意图如下:

Async Resolve -> Callback -> Async Connect -> Callback -> Async Write -> Callback -> Async Read

我省略了解析和绑定等部分。假设 Socket 已经绑定到一个端口并且主机名被解析(所以 connect 意味着建立到端点的真实连接)

现在的重点是我可以用同一个io_service对象启动多个异步连接。这意味着,例如,虽然在我的io_service线程中程序即将获取Async Write一些数据,但主线程将调用Async Resolveon Socket (但使用相同的io_service)。这意味着我io_service现在有一些并行工作要做 - 我想知道它将如何优先处理工作?

例如它是这样的

Main Thread              |      io_service Thread
-------------------------+-----------------------------------------------
SocketA->Async Connect   |
//Some other Stuff       |     SocketA->Callback from Async Connect
                         |     SocketA->Async Write
SocketB->Async Connect   |      
                         |     --> ?

现在在这一点上,我不得不承认我不太确定它是如何io_service工作的。在第四行中,现在需要执行两个不同的异步函数。

是否io_service能够Async Connect同时Async Write进行?如果是这种情况,很明显总是会调用首先完成的函数的回调。

如果io_service没有能力这样做,它将按什么顺序完成工作如果SocketA Async Write将首先调用,它的回调也将首先被调用。实际上,在 SocketA 上的整个操作完成之前,总会有工作。

编辑 :

根据 ereOns 的评论,我试图让我的问题更加准确:

io_service线程的角度来看——SocketA Async Connect调用是异步的还是同步的?从我的主线程的角度来看,它当然是异步的(它只是调度命令然后继续)。但是在io_service线程中这个特定的Connect调用会阻塞其他操作吗?

换句话说:一个io_service人在读取另一个套接字时是否能够连接到一个套接字?

另一个例子是,如果我Async Connect在我的 main 函数中一个接一个地调用 2:

SocketA->AsyncConnect();
SocketB->AsyncConnect();

假设来自 SocketA 的主机有点慢,需要两秒钟才能回答。因此,当 SocketA 尝试连接时,SocketB 会同时连接还是必须等到 SocketA 完成/超时?

4

2 回答 2

4

所有工作都在io_service.run()运行的线程中完成。

但是,对任何async_方法的调用都不会io_service.run()阻塞这个特定线程:它的行为与在多个事件上调用时完全一样select(),并且每当引发此类事件时都会“返回”(调用回调)。也就是说,如果你打电话:

socketA->async_connect();
socketB->async_connect();

socketB还不如先连接,socketA然后首先调用关联的回调,仍然在线程io_service.run()运行中。

这就是 Boost Asio 的全部优点:它会在更合适的时候非常小心地处理轮询、等待和引发事件,从而为您留下“简单”的部分。

于 2012-05-10T12:09:58.367 回答
1

您不应该在这里尝试预测异步操作的执行顺序。async_connect只需发出信号io_service并立即返回。真正的工作是在io_service对象的事件处理循环 ( io_service::run) 中完成的,但您不知道确切的细节。它很可能使用特定于操作系统的异步 IO 功能。

目前尚不清楚您要达到的目标。也许你应该使用同步操作。也许您应该使用线程同步功能。也许io_service::run_one会帮助你(它最多执行一个处理程序)。

也许你会想io_service::run在不同的线程中多次调用,创建一个线程池。这样一个长完成处理程序就不会阻塞所有其他处理程序。

boost::asio::io_service service;
const size_t ASIO_THREAD_COUNT = 3;
boost::thread_group threadGroup;
for (size_t i = 0; i < ASIO_THREAD_COUNT; ++i)
        threadGroup.create_thread(boost::bind(&boost::asio::io_service::run,
            &service, boost::system::error_code()));
于 2012-05-10T13:05:02.270 回答