如何在等待时取消 `boost::asio::read` 操作
how to cancel a `boost::asio::read` operation while it's waiting
我正在使用 boost::asio
在客户端和服务器之间来回传输数据。我在客户端有一个 reader 线程来读取在客户端套接字上接收到的数据。请注意,我在客户端使用 boost::asio::read
,在服务器端使用 boost::asio::write
。
不使用 async_read
或 async_write
。一切都很好。
然而,当我关闭我的应用程序时,10 次中有 2 次该应用程序没有完全拆除或正确关闭。关闭时挂起问题如下:
我的关闭函数在我的应用程序关闭期间调用析构函数时被调用。以下是关闭函数的代码:
socket.cancel();
socket.close();
boost::system::error_code ec;
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
问题是 boost::asio::read
调用在未获取任何数据并一直等待时不会 return。只要我可以取消它,这应该没问题。我正在尝试对其执行 socket.cancel
以在退出时取消所有读取操作。
但是,它似乎不起作用。我在一些论坛上读到 socket.cancel
只取消 async_read
操作。是这样吗 ? 那么当我的应用程序需要退出时,取消boost::asio::read`操作的方法是什么?
这就是阻塞IO的本质。
确实socket.cancel()
(甚至io_service::stop()
)不会对同步操作起作用。
中断它的唯一方法是使用套接字级超时(但 Asio 不公开它)或使用异步信号(例如,在终端中按 Ctrl-C 向子进程发送 SIGINT)。
如果您坚持 运行 具有超时的单个操作,我之前创建了一个穷人的包装器:
boost::system::error_code _error_code;
client_socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, _error_code);
以上代码帮助我立即关闭同步读取。
并同步读取 return,错误代码:boost::asio::error::eof
我想知道为什么您的代码 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
不起作用。
也许你应该再试一次。
错误是由于在调用 socket.shutdown()
之前调用了 socket.close()
。如果在有挂起的同步 read()
时关闭套接字,您偶尔会遇到该错误。这实际上是由于底层 asio 套接字代码中预期的数据竞争。
尝试删除 socket.close()
调用。假设您的套接字被包裹在某种 shared_ptr 中,您可以让套接字析构函数关闭底层套接字。
您仍然需要在用例中显式调用 socket.cancel()
和 socket.shutdown()
以取消未完成的操作。
我正在使用 boost::asio
在客户端和服务器之间来回传输数据。我在客户端有一个 reader 线程来读取在客户端套接字上接收到的数据。请注意,我在客户端使用 boost::asio::read
,在服务器端使用 boost::asio::write
。
不使用 async_read
或 async_write
。一切都很好。
然而,当我关闭我的应用程序时,10 次中有 2 次该应用程序没有完全拆除或正确关闭。关闭时挂起问题如下:
我的关闭函数在我的应用程序关闭期间调用析构函数时被调用。以下是关闭函数的代码:
socket.cancel();
socket.close();
boost::system::error_code ec;
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
问题是 boost::asio::read
调用在未获取任何数据并一直等待时不会 return。只要我可以取消它,这应该没问题。我正在尝试对其执行 socket.cancel
以在退出时取消所有读取操作。
但是,它似乎不起作用。我在一些论坛上读到 socket.cancel
只取消 async_read
操作。是这样吗 ? 那么当我的应用程序需要退出时,取消boost::asio::read`操作的方法是什么?
这就是阻塞IO的本质。
确实socket.cancel()
(甚至io_service::stop()
)不会对同步操作起作用。
中断它的唯一方法是使用套接字级超时(但 Asio 不公开它)或使用异步信号(例如,在终端中按 Ctrl-C 向子进程发送 SIGINT)。
如果您坚持 运行 具有超时的单个操作,我之前创建了一个穷人的包装器:
boost::system::error_code _error_code;
client_socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, _error_code);
以上代码帮助我立即关闭同步读取。
并同步读取 return,错误代码:boost::asio::error::eof
我想知道为什么您的代码 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
不起作用。
也许你应该再试一次。
错误是由于在调用 socket.shutdown()
之前调用了 socket.close()
。如果在有挂起的同步 read()
时关闭套接字,您偶尔会遇到该错误。这实际上是由于底层 asio 套接字代码中预期的数据竞争。
尝试删除 socket.close()
调用。假设您的套接字被包裹在某种 shared_ptr 中,您可以让套接字析构函数关闭底层套接字。
您仍然需要在用例中显式调用 socket.cancel()
和 socket.shutdown()
以取消未完成的操作。