【问题标题】:Properly killing an asio steady_timer after a disconnect断开连接后正确杀死 asio stable_timer
【发布时间】:2019-04-21 17:06:30
【问题描述】:

我使用独立的 asio 编写了一个异步 SSL 套接字实现,并且在服务器重置/关闭连接后努力让它重新连接。我对 asio 库比较陌生,所以请多多包涵。

由于steady_timer,即使在断开连接后,调用io_context::run 的线程仍然被阻塞。我的close() 逻辑负责重置套接字资源,还负责尝试终止计时器。这就是我的代码现在的样子:

创建我的异步作业:

timer.async_wait(std::bind(&ssl_socket::heartbeat, this));

在我的close() 方法中:

timer.expires_at(std::chrono::steady_clock::now());
timer.cancel();

根据boost docscancel()应该:

取消任何正在等待计时器的异步操作。

也许我误解了这一点,但我想这也会取消绑定到 io_context 的异步作业,但事实并非如此。 io_context::run 永远不会被释放并造成死锁。

这是我的计时器处理程序的样子:

void ssl_socket::heartbeat() {
    spdlog::get("console")->trace("heartbeat called");

    if (connected_) {
        write(heartbeat_token);
        spdlog::get("console")->trace("heartbeat sent");
    }

    timer.expires_at(std::chrono::steady_clock::now() + std::chrono::seconds(heartbeat_interval));
    timer.async_wait(std::bind(&ssl_socket::heartbeat, this));

}

我想让处理程序不必验证它是否应该更新其计时器并让close() 处理(如果可能的话)。

【问题讨论】:

  • @tkausl 哎呀,忘了。正在更新 OP。

标签: c++ ssl asio


【解决方案1】:

您忽略了错误代码。

根据 boost 文档,cancel() 应该:

取消任何正在等待计时器的异步操作。

这有点误导。当您阅读cancel 函数的完整描述时,您会看到:

此函数强制完成任何挂起的异步等待 针对计时器的操作。每个取消操作的处理程序 将使用 boost::asio::error::operation_aborted 错误调用 代码。

这意味着,您的处理程序将被取消函数调用,并且由于您的处理程序只是重新设置到期时间并再次等待,因此循环永远不会结束。你需要检查错误代码,如果设置了就退出循环。

if(error) return;

【讨论】:

  • 我已经应用了更新,但收到了构建错误,好像async_wait() 不需要任何参数。我查看了another stackoverflow post,他们也不期待error_code。非常混乱。
  • 您可能需要将std::placeholders::_1 作为第三个参数传递给std::bind
  • 我试过了,收到构建错误。删除它,收到构建错误。我将更新 OP 以反映我现在所拥有的。
  • 我必须更新我的续订以支持添加参数,因此生成错误。好像已经建好了!现在试试这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-13
相关资源
最近更新 更多