如何检测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
相关产品推荐
相关产品推荐

