Boost.Asio:socket :: close不取消aysnc_read_some

时间:2013-09-10 11:10:13

标签: c++ sockets boost boost-asio

我有一个执行async_read_some的增强插槽:

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));

当我的Session课程被删除时socket_.close()被调用。我认为这会取消async_read_some并错误地调用Session::handle_read

然而情况并非如此,并且正在查看 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()

没有提到读取被取消。所以我的问题是,如何取消读取,以便我可以干净地关闭套接字?

2 个答案:

答案 0 :(得分:2)

首先,它应该导致在调用下一个runrun_onepollpoll_one时调用句柄,假设io_service仍处于有效状态。取消/关闭不会突然改变在ASIO中调用处理程序的行为。

因此,如果你在删除Session时触发了这个,你将拥有UB,因为你会在被破坏的对象上调用处理程序,因为你传递了原始指针,被删除了。

我常用的技巧是将shared_ptr与pimpl模式的变体结合使用。我通常在共享指针中实现,并将其传递给各种ASIO调用。当外部接口被破坏时,我在pimpl上调用shutdown方法,这会导致ASIO取消其操作,然后接口重置其共享指针的副本。

一旦ASIO调用存储的处理程序,它将不再具有共享指针的副本,并且破坏将完成。

答案 1 :(得分:0)

就我而言,调用acceptor->close()仅将operation_aborted错误发送到排队的accept_asyncsend_async任务。我的read_some_async没有收到错误。 我发现调用socket->shutdown(socket_base::shutdown_type::shutdown_both);socket->close();会触发错误完成回调。