asio:取消

时间:2016-03-31 12:56:24

标签: c++ boost-asio

我很难在文档中找到明确的答案。

我想知道是否取消异步读取或写入操作,然后重新启动操作会导致数据流损坏?

详细阅读:如果正在运行async_read_some操作:

  • 通过流描述符取消该操作
  • 等待处理程序完成并处理结果(使用operation_aborted或字节传输)。

我可以确定当我开始新的async_read_some操作时,没有数据丢失吗?即当处理程序返回operation_aborted错误时,没有读取数据?

同样适用于async_write_some操作。当我取消操作时,等待处理程序完成,处理结果(再次我知道返回不需要是operation_aborted),然后开始写剩余数据,流是否有可能重复数据?即可以取消导致在恢复写入时双倍写入数据吗?

1 个答案:

答案 0 :(得分:2)

本身cancel()不会导致流中的数据丢失或重复。如果应用程序:

,则只会在应用程序协议中发生数据丢失或重复
  • 使用相同的底层内存启动多个读取操作,而不会处理已读取的数据
  • 启动多个写操作,使用相同的底层内存成功,而不更改已编写的内存内容

正确处理传递给完成处理程序的error_codebytes_transferred可以防止这种形式的数据丢失或重复。如果bytes_transferred大于0,则数据已从套接字读入缓冲区或从缓冲区写入套接字。请注意,如果某个操作已在不久的将来被调用或排队等待调用,则该操作不再可取消。请考虑以下情况:socket可以读取42个字节:

assert(socket.available() == 42);
std::array<char, 32> buffer;
socket.async_read_some(boost::asio::buffer(buffer), ...); // op 1
socket.cancel();
socket.async_read_some(boost::asio::buffer(buffer), ...); // op 2
io_service.run();

如果op 1成功并将32字节读入buffer,则10字节仍可从socket读取。 op 1的完成处理程序将在以后成功排队,error_code成功,bytes_transferred 32。此时,socket.cancel()op 1没有影响。在启动op 2后,10剩余的buffer字节就会准备好进入op 1,从op 2覆盖一些未处理的数据。 error_code的完成处理程序将在以后成功排队,bytes_transferred成功10 error_code

对于非组合操作,例如socket.async_read_some()

  • 如果发生错误,例如取消,则boost::system::errc::success将不会是bytes_transferred0将始终为error_code
  • 如果未发生错误,则boost::system::errc::successbytes_transferred0将大于或等于async_receive()

StreamSocketService async_send()0函数记录了此行为:

  

如果操作成功完成,则调用[handler]并传输字节数。否则,使用error_code调用它。

另一方面,对于组合操作,例如boost::asio::async_read(),可以使用非成功bytes_transferred和非零async_read()来调用处理程序。例如,如果启动async_read_some()操作并在完成之前将其设置为读取1024个字节,则可以多次调用async_read()。如果接收到256个字节然后关闭连接,则error_code处理程序将具有非零bytes_transferred,{{1}}将指示缓冲区的256个字节有效。