[英]Boost.Asio: socket::close not cancelling aysnc_read_some
I have a boost socket doing an async_read_some
: 我有一个执行
async_read_some
的boost套接字:
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&Session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
When my Session
class is deleted socket_.close()
is called. 当我的
Session
类被删除时, socket_.close()
。 I thought this would cancel the async_read_some
and call Session::handle_read
with an error. 我认为这将取消
async_read_some
并调用Session::handle_read
并显示错误。
However this is not the case and looking at basic_socket.hpp 然而,情况并非如此,并且正在查看basic_socket.hpp
/// Close the socket.
/**
* This function is used to close the socket. Any asynchronous send, receive
* or connect operations will be cancelled immediately, and will complete
* with the boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure. Note that, even if
* the function indicates an error, the underlying descriptor is closed.
*
* @note For portable behaviour with respect to graceful closure of a
* connected socket, call shutdown() before closing the socket.
*/
void close()
there is no mention of reads being cancelled. 没有提到读取被取消。 So my question is, how do I cancel the read so I can close the socket cleanly?
所以我的问题是,如何取消读取,以便我可以干净地关闭套接字?
First, it should cause the handle to be called when the next run
, run_one
, poll
, or poll_one
is called, assuming the io_service
is still in a valid state. 首先,假设
io_service
仍处于有效状态,它应该在调用下一次run
, run_one
, poll
或poll_one
调用io_service
。 Canceling/closing does not suddenly change the behavior of how handlers are invoked in ASIO. 取消/关闭不会突然改变在ASIO中调用处理程序的行为。
Because of this, if you're triggering this on deletion of your Session
, you will have UB, since the handler will be invoked on the destroyed object, since you passed it the raw pointer, which has subsequently been deleted. 因此,如果您在删除
Session
触发此操作,则将具有UB,因为将在已销毁的对象上调用处理程序,因为您已将原始指针传递给它,该指针随后被删除。
My usual technique for this is to use shared_ptr
combined with a variant of the pimpl pattern. 我通常使用的技术是将
shared_ptr
与pimpl模式的变体结合使用。 I usually have the implementation in a shared pointer, and pass that to the various ASIO calls. 我通常在共享指针中实现,并将其传递给各种ASIO调用。 When the exterior interface is destroyed, I call a shutdown method on the pimpl which causes ASIO to cancel its operations, and then the interface resets its copy of the shared pointer.
当外部接口被破坏时,我在pimpl上调用shutdown方法,这会导致ASIO取消其操作,然后接口重置其共享指针的副本。
Once ASIO calls of the stored handlers, it will no longer have a copy of the shared pointer, and the destruction will complete. 一旦ASIO调用存储的处理程序,它将不再具有共享指针的副本,并且销毁将完成。
In my case, calling acceptor->close()
only sends operation_aborted error to queued accept_async
and send_async
tasks. 在我的例子中,调用
acceptor->close()
只会向排队的accept_async
和send_async
任务发送operation_aborted错误。 My read_some_async
does not receive error. 我的
read_some_async
没有收到错误。 I found that calling socket->shutdown(socket_base::shutdown_type::shutdown_both);
我发现调用
socket->shutdown(socket_base::shutdown_type::shutdown_both);
and socket->close();
和
socket->close();
will trigger the error completion callback. 将触发错误完成回调。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.