You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Beast SSL握手阶段调用async_shutdown触发断言失败,如何正确关闭流?

解决Beast HTTPS客户端握手期间关闭流触发断言的问题

这个断言错误的核心原因是:Beast的流对象不允许同时存在多个未完成的异步操作。当async_handshake还在执行时调用async_shutdown,就会触发这个检查逻辑,导致断言失败。

以下是几种可行的解决方式:

1. 先取消握手操作,再执行关闭

直接调用流的cancel()方法取消正在进行的async_handshake,该操作会让握手的完成处理函数以boost::asio::error::operation_aborted错误被唤醒。在处理函数中捕获这个错误后,再执行async_shutdown:

// 触发取消操作
stream.cancel();

// 握手完成的处理函数
void on_handshake(boost::system::error_code ec) {
    if (ec == boost::asio::error::operation_aborted) {
        // 取消后执行关闭
        stream.async_shutdown([](boost::system::error_code ec) {
            // 处理关闭后的逻辑,忽略SSL层的一些常见错误
            if (ec && ec != boost::asio::error::eof) {
                // 记录错误
            }
            // 最后关闭底层socket
            stream.next_layer().close();
        });
    } else if (ec) {
        // 处理握手失败的其他情况
        stream.next_layer().close();
    }
}

2. 用strand序列化所有流操作

使用boost::asio::io_context::strand确保所有对Beast流的异步操作(握手、关闭、读写)都串行执行,从根源上避免并发操作冲突:

boost::asio::io_context io_ctx;
boost::asio::io_context::strand strand(io_ctx);

// 提交握手操作
strand.post([&]() {
    stream.async_handshake(boost::beast::ssl::stream_base::client,
        strand.wrap(&on_handshake));
});

// 需要关闭时,通过strand提交关闭逻辑
strand.post([&]() {
    if (stream.next_layer().is_open()) {
        // 如果握手还在进行,先取消
        stream.cancel();
    } else {
        stream.async_shutdown(strand.wrap(&on_shutdown));
    }
});

3. 用状态标记延迟关闭操作

设置一个布尔标志(比如should_shutdown),当需要关闭时先标记该状态,等握手操作完成(无论成功或失败)后,再根据标志执行关闭:

std::atomic<bool> should_shutdown = false;

// 触发关闭请求时设置标志
should_shutdown = true;

// 握手完成处理函数
void on_handshake(boost::system::error_code ec) {
    if (should_shutdown) {
        stream.async_shutdown([](boost::system::error_code ec) {
            // 处理关闭逻辑
            stream.next_layer().close();
        });
        return;
    }
    // 正常握手后的逻辑
}

注意事项

  • 调用cancel()后,要确保握手的处理函数能正确处理operation_aborted错误,避免遗漏关闭逻辑
  • SSL流关闭时可能会返回eof错误,这属于正常情况,可以忽略该错误
  • 所有涉及流的异步操作必须保证序列化,避免并发调用导致的未定义行为

内容的提问来源于stack exchange,提问作者Кирилл Волков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:45:41