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

Boost Beast async_write搭配队列使用时空队列致发送循环中断问题

问题根因

当前的写流程完全依赖on_write回调触发下一次do_write执行:当消息队列为空时,do_write不会发起async_write调用,也就不会产生新的on_write回调,整个写循环就此终止。后续新消息入队时没有触发点重新启动写流程,就会出现消息堆积无法发送的问题。
额外需要注意:Boost.Asio 不允许对同一个 socket 同时发起多个异步写操作,当前代码如果在写过程中有新消息入队,也没有并发保护,存在线程安全风险。

修复方案

1. 新增成员变量

给session类新增2个成员变量:

  • 互斥锁queue_mutex_保护消息队列的并发访问
  • 布尔标记is_writing_记录当前是否有正在进行的异步写操作,避免重复发起写请求
// 原有成员变量
std::queue<nlohmann::json> outgoingMessages;
// 新增成员变量
std::mutex queue_mutex_;
bool is_writing_ = false;

2. 新增线程安全的消息入队接口

所有新消息必须通过这个接口入队,入队后如果当前没有运行中的写操作,就主动触发do_write启动写循环:

void session::push_message(nlohmann::json msg) {
    std::lock_guard<std::mutex> lock(queue_mutex_);
    outgoingMessages.push(std::move(msg));
    // 没有正在进行的写操作,主动启动写流程
    if (!is_writing_) {
        do_write();
    }
}

3. 修改do_write和on_write逻辑

调整逻辑维护is_writing_状态,保证线程安全,同时避免异步写访问野指针:

void session::do_write(void) {
    std::lock_guard<std::mutex> lock(queue_mutex_);
    if (outgoingMessages.empty()) {
        // 队列已空,标记写操作结束,直接返回
        is_writing_ = false;
        return;
    }
    // 标记正在写,避免重复发起异步写
    is_writing_ = true;
    auto message = std::move(outgoingMessages.front());
    outgoingMessages.pop();

    // 用shared_ptr持有序列化后的字符串,避免临时变量提前销毁导致野指针
    auto serialized_msg = std::make_shared<std::string>(message.dump());
    ws_.async_write(
        boost::asio::buffer(*serialized_msg),
        boost::beast::bind_front_handler(&session::on_write, shared_from_this())
    );
}

void session::on_write(boost::beast::error_code errorCode, std::size_t bytes_transferred) {
    if (errorCode)
        return fail(errorCode, "write");

    if (bytes_transferred == 0)
        std::this_thread::sleep_for(std::chrono::milliseconds(1));

    // 触发下一次写操作
    do_write();
}

如果你的整个session逻辑都跑在同一个asio线程上下文里,不需要跨线程操作队列,也可以去掉互斥锁,只保留is_writing_标记即可。

内容的提问来源于stack exchange,提问作者Nicholas J Ingrassellino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:48:04