【问题标题】:Boost.Asio async_handshake cannot be canceledBoost.Asio async_handshake 无法取消
【发布时间】:2016-10-13 16:32:10
【问题描述】:

当使用 Boost Asio SSL 流启动 async_handshake,然后在握手完成之前实现一个截止时间计时器以取消/关闭流时,程序将因缓冲区溢出异常而崩溃(在 Windows 上,我没有尝试过Linux)。崩溃发生在套接字为closed 之后,外部处理程序完成执行,但在run() 命令完成之前。

在进行 SSL 握手时,是否有无法关闭套接字的原因?或者这是 Boost Asio 中的错误?

class Connection
{
    void connect_handler(const boost::system::error_code &err)
    {
        ...
        ssock->async_handshake(boost::asio::ssl::stream_base::client,
                   boost::bind(&Connection::handle_handshake, this, _1));
        ...
    }

    void handle_handshake(const boost::system::error_code &err)
    {
        // CONNECTED SECURELY
    }

    void handle_timeout()
    {
        // HANDLE SSL SHUTDOWN IF ALREADY CONNECTED...
        ...
        ssock->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
        ssock->close();
        delete ssock;
    }

    ...

    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> *ssock;
};

澄清一下,在 IO 服务调用 handle_handshake() 之前调用 handle_timeout() 会在 io_service::run() 方法中崩溃。

【问题讨论】:

  • timeout 之后,您的Connection 对象是否仍在范围内?见boost-async-functions-and-shared-ptrs
  • 必须如此,因为io_serviceConnection 类的成员。该成员的io_service::run() 方法在退出前会崩溃,因此看起来像是OpenSSL 的内部问题。超时适用于所有标准 TCP 作业。
  • io_service 成为连接的成员是不寻常的,它通常是更高级别的对象。我建议将其从您的 Connection 课程中删除,并确保其范围持续到(至少)main() 结束...

标签: c++ sockets ssl boost


【解决方案1】:

我们也遇到过这种情况。我的同事 (AW) 找到了罪魁祸首。 Handshake 在后台使用读写操作,需要取消这些操作,并且握手操作需要正确完成(带有 operation_aborted 错误)才能安全关闭 ssock。对此的测试解决方案如下:

void handle_timeout() {
  ...

  // cancel pending read/write operations
  ssock->lowest_layer().cancel();

  // finish shutdown on next tick of event loop
  boost::asio::post([=] {
    ssock->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
    ssock->close();
    delete ssock;
  });
}

【讨论】:

    【解决方案2】:

    问题是套接字对象在异步处理程序完成之前被销毁。要取消挂起/排队的处理程序,请像这样使用io_service::stop()

    io_service.stop(); // Stop the IO service to prevent handlers from executing
    ssock->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
    ssock->close();
    delete ssock;
    

    所以不,这不是 Boost.Asio 本身的错误。

    【讨论】:

      猜你喜欢
      • 2011-04-24
      • 2020-08-23
      • 1970-01-01
      • 2022-09-27
      • 2018-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多