使用Tungstenite连接Binance Websocket API遇400错误的原因排查
连接Binance WebSocket遇到400错误的问题与解决
问题描述
我尝试使用Rust的tungstenite库连接Binance WebSocket服务器,相关代码、依赖配置及报错信息如下:
连接代码
use tungstenite::{connect, Message}; use url::Url; fn main() { let (mut socket, response) = connect(Url::parse("wss://stream.binance.com:9443/ws/BNBBTC@aggTrade").unwrap()).expect("Can't connect"); println!("Connected to the server"); println!("Response HTTP code: {}", response.status()); println!("Response contains the following headers:"); for (ref header, _value) in response.headers() { println!("* {}", header); } }
Cargo.toml依赖配置
[dependencies] tungstenite = "0.17.3" url = "2.3.1"
报错信息
thread 'main' panicked at 'Can't connect: Http(Response { status: 400, version: HTTP/1.1, headers: {"server": "awselb/2.0", "date": "Sat, 22 Oct 2022 20:23:40 GMT", "content-type": "text/html", "content-length": "220", "connection": "close"}, body: None })', src/main.rs:6:90 stack backtrace: 0: rust_begin_unwind at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:584:5 1: core::panicking::panic_fmt at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:142:14 2: core::result::unwrap_failed at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1814:5 3: core::result::Result<T,E>::expect at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1064:23 4: untitled12::main at ./src/main.rs:6:9 5: core::ops::function::FnOnce::call_once at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
根据Binance官方WebSocket API文档,请求格式应该合规,请问错误原因是什么?遗漏了哪些内容?
错误原因与修复方案
错误原因
400错误是因为tungstenite 0.17.3版本的connect函数在构建WebSocket握手请求时,没有自动添加正确的Host请求头,而Binance的WebSocket服务器对请求头的完整性有严格要求,缺少Host头会被判定为无效请求,直接返回400错误。
修复方案
有两种可行的解决方式:
方式一:手动添加Host请求头
通过tungstenite::client::IntoClientRequest自定义握手请求,手动插入Host头:
use tungstenite::{client::IntoClientRequest, connect, Message}; use url::Url; fn main() { let url = Url::parse("wss://stream.binance.com:9443/ws/BNBBTC@aggTrade").unwrap(); // 构建自定义请求并添加Host头 let mut request = url.into_client_request().unwrap(); request.headers_mut().insert( "Host", "stream.binance.com:9443".parse().unwrap(), ); let (mut socket, response) = connect(request).expect("Can't connect"); println!("Connected to the server"); println!("Response HTTP code: {}", response.status()); println!("Response contains the following headers:"); for (ref header, _value) in response.headers() { println!("* {}", header); } }
方式二:升级tungstenite版本
新版本的tungstenite(0.20+)会自动处理Host头的正确设置,无需手动配置。修改Cargo.toml的依赖版本:
[dependencies] tungstenite = "0.20.0" url = "2.3.1"
验证说明
Binance的WebSocket服务器需要握手请求包含正确的Host头部,以确保请求被路由到正确的端点。采用上述任一方式后,即可正常建立WebSocket连接。
内容的提问来源于stack exchange,提问作者avernus
相关产品推荐
相关产品推荐

