c++ - 当服务器异常关闭时,boost.asio async_write 超时不起作用
问题描述
我参考了 boost 示例中的示例:async_tcp_client.cpp。此示例显示如何为 aync_read 设置超时。所以我根据这个例子写了一个测试程序来测试async_write超时。编写代码为:
bool AsioAsyncTCPClientImpl::send(const uint8_t* data, int32_t length)
{
if (!m_isConnected || length <= 0) return false;
m_deadline.expires_after(std::chrono::seconds(5));
boost::system::error_code ec;
boost::asio::async_write(m_client, boost::asio::buffer(data, length),
std::bind(&AsioAsyncTCPClientImpl::handleWrite, this, std::placeholders::_1, std::placeholders::_2));
return true;
}
handleWrite 代码是:
void AsioAsyncTCPClientImpl::handleWrite(const boost::system::error_code& ec, std::size_t len)
{
if (!m_started) return;
if (ec == boost::asio::error::eof)
{
fireConnectionCallback(ConnectionState::Disconnected);
return;
}
if (ec)
{
fireErrorCallback(ec);
return;
}
m_deadline.expires_at(boost::asio::steady_timer::time_point::max());
}
根据我的测试,如果我禁用网络或拔出运行服务器的 PC 的电缆,async_write 将始终正常完成,因此超时设置不起作用。我想知道我是否遗漏了什么,希望熟悉这方面的人能给我一些线索,谢谢提前!
更新
async_wait 代码:
bool AsioAsyncTCPClientImpl::start()
{
if (m_started) return true;
connect();
m_deadline.async_wait(std::bind(&AsioAsyncTCPClientImpl::checkTimeout, this));
m_started = true;
m_ioLoopThread = std::thread(&AsioAsyncTCPClientImpl::loopProcess, this);
return true;
}
void AsioAsyncTCPClientImpl::checkTimeout()
{
if (!m_started) return;
if (m_deadline.expiry() <= boost::asio::steady_timer::clock_type::now())
{
std::cout << "wait timeout" << std::endl;
disconnect();
m_deadline.expires_at(boost::asio::steady_timer::time_point::max());
}
m_deadline.async_wait(std::bind(&AsioAsyncTCPClientImpl::checkTimeout, this));
}
我将 io_context 的 run 方法放在一个线程中,我不确定这是否是正确的方法,因为我不想在 main 函数中运行 io_context.run() 。
void AsioAsyncTCPClientImpl::loopProcess()
{
while(m_started)
{
m_context.run();
}
std::cout << "loop process exited" << std::endl;
}
解决方案
你永远不会等待计时器。
就像是
m_deadline.async_wait(
std::bind(&AsioAsyncTCPClientImpl::handleTimer, this, boost::asio::placeholders::errpr));
接着
void AsioAsyncTCPClientImpl::handleTimer(boost::system::error_code ec) {
if (!ec) {
std::cout << "Timeout expired" << std::endl;
m_client.cancel();
}
}
推荐阅读
- rust - 为什么在闭包中调用函数与在 Rust 中直接调用函数时生命周期不同?
- excel - 如何在 VBA 中将自动生成的单选按钮设置为 true?
- assembly - MIPS中rem和mfhi的区别
- python - 如何提取元素中标签后的文本
- javascript - 欧芹:如何不对某些事件进行验证
- selenium - 如何通过整个网站验证并获得所有 href="javascript:void(0)" 的响应,而不仅仅是使用 selenium 的单页
- r - 编织到 PDF 时,RStudio 不会显示 Unicode 字符
- javascript - jQuery遍历可排序的树结构
- unit-testing - 如何在读取响应正文时强制出错
- android - 从列表视图中单击按钮时,如何传递项目的索引?