asio:取消后重新启动async_read_some/async_write_some是否安全
asio: is it safe to restart a async_read_some/async_write_some after cancel
我很难在文档中找到确切的答案。
我想知道取消异步读写操作,然后重新启动操作是否会导致数据流损坏?
详细阅读:如果正在运行async_read_some操作:
- 通过流描述符取消该操作
- 等待处理程序完成并处理结果(使用operation_aborted或字节传输)
我能确定当我启动一个新的async_read_some操作时,没有数据丢失吗?也就是说,当处理程序返回operation_aborted错误时,没有读取任何数据?
async_write_some操作也是如此。当我取消操作,等待处理程序完成,处理结果(我再次知道返回不需要operation_abored),然后开始写入剩余数据时,流是否可能重复数据?即,当恢复写入时,取消是否会导致数据被双重写入?
cancel()
本身不会导致流中的数据丢失或重复。只有当应用程序:时,数据丢失或重复才会发生在应用程序协议中
- 使用相同的底层内存启动多个读取操作,这些操作在不处理已读取的数据的情况下成功
- 使用相同的底层内存启动多个写入操作,这些操作在不更改已写入内存的内容的情况下成功
正确处理传递给完成处理程序的error_code
和bytes_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
。
对于非合成操作,如socket.async_read_some()
:
- 如果发生错误,例如取消,则
error_code
将不是boost::system::errc::success
,而bytes_transferred
将始终是0
- 如果没有出现错误,则
error_code
将为boost::system::errc::success
,bytes_transferred
将大于或等于0
StreamSocketService的async_receive()
和async_send()
函数记录了这种行为:
如果操作成功完成,则会调用[handler]并传输字节数。否则使用
0
调用它。
另一方面,对于组合操作,例如boost::asio::async_read()
,可以使用不成功的error_code
和非零的bytes_transferred
来调用处理程序。例如,如果async_read()
操作被启动并设置为在完成之前读取1024字节,则它可以多次调用async_read_some()
。如果接收到256个字节,然后连接关闭,则async_read()
处理程序将具有非零的error_code
,并且bytes_transferred
将指示缓冲器的256个字节是有效的。
- 为什么std::async使用同一个线程运行函数
- 为什么可以将左值传递给"std::async",即使它引用了右值
- 使用用户定义的参数调用future/async并调用类方法
- 使用 std::async 时死锁,将来作为成员
- 为什么我不能将引用作为 std::async 的函数参数传递
- std::async from std::async in windows xp
- Google Cloud Pubsub Async Streaming API in C++
- -fno-unwind-tables 和 -fno-async-unwind-tables 不起作用 NDK clang
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- std::async 不会立即调用
- async中没有匹配的函数(模板中未解析的类型)
- 为什么以下代码块提供输出"ZZZ(some garbage value)"而不是"ZZ(some garbage value)"
- 错误:在类型 "blah blah" 的绑定引用中删除限定符以初始化"some other blah blah"
- std::async 如果线程是从 DLL 创建的,则会阻止进程退出?
- 使用 std::vector<std::future<int>> 和 std::async 启动几个线程时中止
- 在Visual Studio中,与std::async一起使用时不调用"thread_local"变量"析构函数,这是一个错误吗?
- 如何称呼表达式"T (&some(...))[2]' 其中 T=字符
- 可能的 std::async 实现错误 Windows
- 为什么使用线程池时嵌套调用 boost::async 会阻塞?
- C++从 std::async 函数读取命名空间中的全局变量标志