是否保证将数据发送到具有boost :: asio的套接字的顺序?
也就是说,我正在多次调用
boost::asio::async_write(socket, buffer, completionHandler)
我看到一些奇怪的行为,客户端显然没有收到我认为我发送的数据,所以我想确保这样做是我希望它正在做的事情。请注意,我不是在等待每次写入之间调用完成处理程序,我只是触发了一堆async_write调用,天真地期望数据以相同的顺序写入套接字。
asio中的strand文档说:
如果存在与连接相关联的单链异步操作(例如,在像HTTP这样的半双工协议实现中),则不可能同时执行处理程序。这是一个隐含的链。
我认为这意味着使用strand不会改变任何东西,因为socket提供了一个隐含的链。
一般来说,strand文档讨论了严格的事件处理程序的顺序调用。但是,我不清楚写入连接的数据是否会按照我调用async_write的顺序写入。
是否保证将数据写入套接字的顺序?
答案 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)是混淆的常见原因。