boost :: asio:发送到套接字的数据的排序

时间:2017-08-22 09:29:26

标签: c++ boost-asio

是否保证将数据发送到具有boost :: asio的套接字的顺序?

也就是说,我正在多次调用

boost::asio::async_write(socket, buffer, completionHandler)

我看到一些奇怪的行为,客户端显然没有收到我认为我发送的数据,所以我想确保这样做是我希望它正在做的事情。请注意,我不是在等待每次写入之间调用完成处理程序,我只是触发了一堆async_write调用,天真地期望数据以相同的顺序写入套接字。

asio中的strand文档说:

  

如果存在与连接相关联的单链异步操作(例如,在像HTTP这样的半双工协议实现中),则不可能同时执行处理程序。这是一个隐含的链。

我认为这意味着使用strand不会改变任何东西,因为socket提供了一个隐含的链。

一般来说,strand文档讨论了严格的事件处理程序的顺序调用。但是,我不清楚写入连接的数据是否会按照我调用async_write的顺序写入。

是否保证将数据写入套接字的顺序?

2 个答案:

答案 0 :(得分:3)

不允许在另一个正在进行时调用async_write。无论您使用的是一个线程还是多个线程,都是如此。来自asio docs

  

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

编辑:对此的解决方法是维护要写入的字节缓冲区,并在写入已在进行时添加到该缓冲区而不是调用async_write。当前写入完成后,再次使用该缓冲区调用async_write

编辑2:this question的答案有一个如何做到这一点的例子。它使用strands,因此可以在多线程应用程序中工作(但如果你的应用程序是单线程的,那么它比必要的复杂一点)。

编辑3:最后的澄清。使用strand不会有帮助,因为strand保证您的代码(对于该strand)只在一个线程中同时运行,但不保证一次只发生一个操作。换句话说,如果你在一个处理程序中调用async_write,那么一旦处理程序返回就可以在该链中调用更多东西,即使async_write仍在进展。您需要手动存储一些状态,指示您已启动async_write和(此处为关键部分)更新作为参数传递给async_write的完成处理程序中的状态。

答案 1 :(得分:0)

你没有说过你的线程,有多少线程同时发送数据? io_service.run()有多少线程?我不知道Asio是否在写入套接字时进行任何同步,我认为它不是因为套接字写入已经是线程安全的。

我建议检查数据缓冲区(发送到套接字的缓冲区)或数据接收逻辑的数据争用。

TCP流媒体性质(如评论中提到的@Some_programmer_dude)是混淆的常见原因。