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

Boost.Beast WebSocket如何让async_read排队避免io_context.run提前退出

Boost.Beast WebSocket客户端ioc.run()提前退出问题解决方案

基础方案:正确实现循环读逻辑(覆盖你提到的两点要求)

你遇到的核心问题是异步任务提交的时间间隙导致io_context误判无待办任务,按以下方式落地官方给出的两点方案即可覆盖基础逻辑:

  1. 封装独立的do_read()函数统一发起读请求,避免重复代码
  2. 在on_read()末尾和握手成功回调中都调用do_read(),保证读请求持续排入io_context

对应实现代码如下:

// 类成员函数:独立封装的读请求发起入口
void session::do_read()
{
    io_in_progress_ = true;
    ws_.async_read(
        buffer_,
        std::bind(
            &session::on_read,
            shared_from_this(),
            std::placeholders::_1,
            std::placeholders::_2
        )
    );
}

// 读回调逻辑
void session::on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
    io_in_progress_ = false;
    boost::ignore_unused(bytes_transferred);

    if(ec)
        return fail(ec, "read");
    
    std::cout << "on_read callback : " << boost::beast::buffers(buffer_.data()) << std::endl;
           
    // 清空缓冲区准备下一次读
    buffer_.consume(buffer_.size());
    // 末尾调用do_read发起下一轮读,保证任务连续
    do_read();
}

// 握手成功回调中首次调用do_read启动读循环
void session::on_handshake(boost::system::error_code ec)
{
    if(ec)
        return fail(ec, "handshake");
    // 启动首次读
    do_read();
    // 若有初始写入需求可在此处发起async_write
}

Boost 1.70+ 版本优化方案(@sehe提到的executor方案落地)

如果已经升级到Boost 1.70及以上版本,可通过加执行器工作守卫彻底解决间隙退出问题:

// 类成员变量声明
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work_guard_;

// 构造函数中初始化守卫,绑定io_context
session::session(boost::asio::io_context& ioc)
    : work_guard_(boost::asio::make_work_guard(ioc))
    // 其他成员初始化逻辑
{}

// 确定要关闭连接时手动释放守卫,允许io_context正常退出
void session::close()
{
    ws_.async_close(boost::beast::websocket::close_code::normal,
        [self = shared_from_this()](boost::system::error_code ec) {
            self->work_guard_.reset();
        });
}

Boost 1.67 兼容解决方案

1.67版本没有executor_work_guard,可使用旧版io_context::work实现相同的守卫效果:

// 类成员变量声明
std::unique_ptr<boost::asio::io_context::work> work_;

// 构造函数中初始化work对象
session::session(boost::asio::io_context& ioc)
    : work_(std::make_unique<boost::asio::io_context::work>(ioc))
    // 其他成员初始化逻辑
{}

// 关闭连接时释放work对象,允许io_context退出
void session::close()
{
    ws_.async_close(boost::beast::websocket::close_code::normal,
        [self = shared_from_this()](boost::system::error_code ec) {
            self->work_.reset();
        });
}

内容的提问来源于stack exchange,提问作者mqmarathon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:36:03