2012-05-10 80 views
7

我正在使用boost::asio::io_service来管理某些异步TCP通信。这意味着我创建了一个boost::asio::ip::tcp::socket并给它io_service。当我开始通信不言而喻示意图如下:boost :: asio :: io_service如何优先工作?

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

我ommitted喜欢决心和绑定的部分。假设Socket已被绑定到端口并且主机名已解析(因此连接意味着建立与端点的真实连接)

现在重点是我可以用同一个io_service对象启动多个异步连接。这意味着,例如,在我的io_service线程中,程序中的某些数据即将到达Async Write,主线程将在Socket上调用Async Resolve(但具有相同的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 ConnectAsync Write吗?如果是这种情况,很明显总是会调用首先完成的函数的回调。

如果io_service而不是能够这样做,它的顺序是什么?如果SocketA Async Write将首先被调用,它的回调函数也将被首先调用。事实上,在SocketA的整个操作完成之前,总会有工作。

编辑:

根据ereOns发表评论我尽量让我的问题有点更精确:

io_service线程的观点 - 是SocketA Async Connect调用异步或同步?从我的主线程来看,它当然是异步的(它只是分派命令,然后继续)。但是在io_service线程中这个具体的Connect调用会阻塞其他操作吗?

换句话说:一个单一的io_service能够连接到一个套接字,而它正在读另一个套接字?

另一个例子是,如果我只需要调用2 Async Connect在我的主要功能之后对方:

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

比方说,从的SocketA主机是有点慢,它需要它两秒钟回答。所以,虽然SocketA试图连接,同时SocketB也会连接,或者它将不得不等待,直到SocketA完成/超时?

+1

我不知道,完全让你的问题,但我会说短耳将尽快引发事件,无论是连接或写,以先到者为准,未指定顺序。如果我可能会问,为什么你认为订单很重要? – ereOn

+0

@ereOn我在问题中添加了一些内容以使其更精确 – Toby

回答

3

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

然而,在调用任何async_方法不会块这种特定线程:它的行为完全一样,如果io_service.run()几个事件称为select()和“收益”(调用回调函数),只要这种引发事件。也就是说,如果您拨打:

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

socketB可以socketA之前以及连接和相关联的回调将被首先调用,还是在线程io_service.run()运行。

这就是Boost Asio的全部美妙之处:当它更合适时,需要非常好地关注投票,等待和提高事件,让您感到“轻松”。

+1

好吧,这是“真正”异步的,这意味着'async_'方法可以并行工作。首先调用哪个回调函数取决于哪个'async_'函数首先返回“?我有这个权利吗? – Toby

+0

@Toby:没错。 – ereOn

+0

由于来自“this”的新答案,我需要再次提问:我们从IO_Service线程的角度来看这里。我很清楚主线程中的async_call将立即返回。然而,回调将在io_service线程中调用...对吗?! – Toby

0

您不应该在此尝试预测异步操作的执行顺序。 async_connect只是信号到io_service并立即返回。真正的工作在io_service对象的事件处理循环(io_service::run)中完成,但您不知道确切的细节。它很可能使用OS特定的异步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())); 
+0

这是错误的。如果'io_service :: run()'只是在驱逐线程中阻塞调用,那么Boost Asio的意义何在?您不需要为此创建多个线程,更不用说线程池。你正在制造一个恐怖来解决一个从未存在的问题。 – ereOn

+0

也许我假设太多,而不是假设太多。但众所周知,处理程序是从'run'-thread调用的。虽然我不确定你对线程池不太满意,但它与Boost.Asio一起很好,很整齐:引用了[doc](http://www.boost.org/doc/libs/1_49_0/doc/) HTML/boost_asio /概述/核心/线程。html):'多线程可能会调用io_service :: run()来设置线程池,从中可以调用完成处理程序' –

+0

需要时线程池没有错。但是对于这里的具体情况来说,Boost Asio被设计为可以一致地处理异步事件,这太过于夸张了。 – ereOn

相关问题