在boost网站中,关于异步操作的超时有一个很好的example。但是,在该示例中,套接字关闭以取消操作。还有socket :: cancel(),但是在文档和编译器警告中,它都表示在可移植性方面存在问题。
在SO中的Boost.Asio超时问题堆栈中,有几种答案。第一个可能是引入自定义事件循环,即循环io_service :: run_one()并在截止日期取消事件循环。我在工作线程中使用io_service :: run()。如果可能的话,这不是我想要使用的解决方案,因为我不想更改我的代码库。
第二个选项是直接更改本机套接字的选项。但是,如果可能的话,我想坚持使用Boost.Asio,并尽可能避免任何类型的平台特定代码。
文档中的示例是旧版本的Boost.Asio,但它正常工作,而不是被迫关闭套接字以取消操作。使用文档示例,我有以下
void check_deadline(const boost::system::error_code &ec)
{
if(!running) {
return;
}
if(timer.expires_at() <= boost::asio::deadline_timer::traits_type::now()) {
// cancel all operations
boost::system::error_code errorcode;
boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
socket.close(errorcode);
if(errorcode) {
SLOGERROR(mutex, errorcode.message(), "check_deadline()");
}
else {
SLOG(mutex, "timed out", "check_deadline()");
// connect again
Connect(endpoint);
if(errorcode) {
SLOGERROR(mutex, errorcode.message(), "check_deadline()");
}
}
// set timer to infinity, so that it won't expire
// until a proper deadline is set
timer.expires_at(boost::posix_time::pos_infin);
}
// keep waiting
timer.async_wait(std::bind(&TCPClient::check_deadline, this, std::placeholders::_1));
}
这是注册到async_wait的唯一回调函数。我可以提出的第一个解决方案是在关闭套接字后重新连接。现在我的问题是,有更好的方法吗?通过更好的方式,我的意思是取消基于计时器的操作,而不会实际中断(即,不关闭套接字)连接。