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

如何基于boost::beast维持WebSocket长连接?

解决Boost.Beast WebSocket异步客户端自动断开的问题

我明白你遇到的困扰——就算移除了on_read里的关闭代码,连接还是会在单次读取完成后断开,而且io_context也跟着退出了。这其实是因为示例里的session对象在on_read结束后没有绑定新的异步操作,导致它的shared_ptr引用计数降到0,对象被销毁,WebSocket连接自然就断了,同时io_context因为没有待处理的任务,直接停止运行。

核心原因拆解

Boost.Beast的异步模型依赖std::shared_ptr管理session的生命周期:当最后一个绑定到session的异步操作完成后,如果没有新的异步任务启动,shared_ptr的引用计数会归零,session被销毁,连接也就跟着关闭了。而io_context.run()本身就是在所有任务完成后自动退出的。

具体解决方案

要让连接持续保持,且io_context一直运行到你显式关闭,需要做两件关键的事:

1. 在on_read完成后,再次发起异步读操作

这会形成一个持续的读取循环,维持session的生命周期,让连接一直活跃。修改你的on_read函数:

void on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
    boost::ignore_unused(bytes_transferred);

    if(ec)
        return fail(ec, "read");

    // 处理收到的消息(比如打印、业务逻辑处理)
    std::cout << boost::beast::buffers_to_string(buffer_.data()) << std::endl;
    buffer_.consume(buffer_.size());

    // 关键:再次发起异步读,维持读取循环
    ws_.async_read(
        buffer_,
        std::bind(
            &session::on_read,
            shared_from_this(),
            std::placeholders::_1,
            std::placeholders::_2));
}

2. 添加显式关闭的机制

你需要一个主动关闭连接并停止io_context的方式。可以给session类新增一个close方法,主动发起WebSocket关闭流程:

class session : public std::enable_shared_from_this<session>
{
    // ... 已有成员变量 ...
    boost::asio::io_context& ios_; // 持有io_context的引用

public:
    // 构造函数中传入io_context引用
    session(boost::asio::io_context& ios) : ios_(ios), ws_(ios) {}

    void close()
    {
        // 发起异步关闭操作
        ws_.async_close(
            boost::beast::websocket::close_code::normal,
            std::bind(
                &session::on_close,
                shared_from_this(),
                std::placeholders::_1));
    }

private:
    void on_close(boost::system::error_code ec)
    {
        if(ec)
            return fail(ec, "close");

        // 关闭底层套接字,并停止io_context
        ws_.next_layer().close();
        ios_.stop();
    }

    // ... 已有方法 ...
};

3. 确保io_context持续运行

只要你的读取循环不中断,io_context就会一直处理异步读任务。当你需要关闭时,调用session::close(),on_close里的ios_.stop()会让ios.run()退出。

额外小贴士

  • 可以给WebSocket设置心跳参数,避免长时间无数据被服务器主动断开:
    ws_.set_option(boost::beast::websocket::stream_base::timeout::suggested(boost::beast::role_type::client));
    
  • 如果需要同时处理多个连接或其他异步任务,io_context可以一直运行,直到你主动调用stop()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:37:00