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

如何检测websocket::stream::async_handshake()的target不存在的情况

问题原因

你的推测是正确的,websocket::stream的async_handshake方法内部已经完成了完整的HTTP握手请求/响应流程,服务端返回的HTTP响应数据已经被WebSocket层完全消费,所以握手完成后再对下层流执行http::async_read无法读取到任何数据,回调自然不会触发。

可行实现方案

共有两种常用的实现方案,可根据你的Boost版本选择:

方案1:使用内置握手响应获取接口(推荐,Boost >= 1.70)

Boost.Beast 1.70及以上版本提供了get_handshake_response()接口,就算握手返回错误,你也可以通过该接口拿到服务端返回的完整HTTP响应,直接判断状态码即可:

void start_ws_handshake()
{
    m_websockStream.async_handshake("your-host.com", "/target/path",
        [this, self = shared_from_this()](beast::error_code ec)
        {
            // 先处理握手失败的场景,读取响应判断错误类型
            if (ec == websocket::error::handshake_failed)
            {
                auto const& resp = m_websockStream.get_handshake_response();
                if (resp.result() == http::status::not_found)
                {
                    return fail("path not found", m_callback);
                }
                // 其他握手错误处理逻辑
                return fail(ec, "handshake failed", m_callback);
            }
            if (ec)
            {
                return fail(ec, "handshake", m_callback);
            }
            // 握手成功,正常执行WebSocket读逻辑
            m_websockStream.async_read(m_buffer, beast::bind_front_handler(&WsSession::on_read, self));
        });
}

方案2:手动完成HTTP握手校验(全版本兼容)

如果你的Boost版本低于1.70,可以手动完成WebSocket握手的HTTP请求发送、响应读取校验,确认符合要求后再将控制权移交WebSocket层:

void start_manual_handshake()
{
    // 构造标准WebSocket握手请求
    http::request<http::empty_body> ws_req;
    ws_req.method(http::verb::get);
    ws_req.target("/target/path");
    ws_req.set(http::field::host, "your-host.com");
    ws_req.set(http::field::upgrade, "websocket");
    ws_req.set(http::field::connection, "Upgrade");
    ws_req.set(http::field::sec_websocket_key, websocket::detail::make_sec_websocket_key());
    ws_req.set(http::field::sec_websocket_version, "13");

    // 手动发送握手请求
    http::async_write(m_websockStream.next_layer(), ws_req,
        [this, self = shared_from_this()](beast::error_code ec, std::size_t)
        {
            if (ec) return fail(ec, "write handshake request", m_callback);
            // 手动读取握手响应
            http::async_read(m_websockStream.next_layer(), m_buffer, m_httpRes,
                [this, self = shared_from_this()](beast::error_code ec, std::size_t)
                {
                    if (ec) return fail(ec, "read handshake response", m_callback);
                    // 自定义状态码校验
                    if (m_httpRes.result() == http::status::not_found)
                    {
                        return fail("path not found", m_callback);
                    }
                    if (m_httpRes.result() != http::status::switching_protocols)
                    {
                        return fail("invalid handshake status", m_callback);
                    }
                    // 校验通过,将响应交给WebSocket层后续处理
                    m_websockStream.set_handshake_response(m_httpRes);
                    // 正常执行WebSocket读逻辑
                    m_websockStream.async_read(m_buffer, beast::bind_front_handler(&WsSession::on_read, self));
                });
        });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:24:04