如何在Rust中实现可正常运行的WebSocket客户端?
问题根因分析
- 第一段代码错误使用了
listen方法:ws库的listen是用于启动WebSocket服务端监听端口的API,实现客户端应该调用connect方法,这是最核心的错误。 - 第二段代码的发送时机错误:直接在
connect的入参闭包里执行发送逻辑,此时WebSocket连接还未完成握手,on_open回调还没触发,消息发不出去也不会报错,连接握手完成后自然也不会再执行你的发送逻辑。 - 缺少TLS支持:你要连接的是
wss开头的加密WebSocket地址,默认的ws库没有开启TLS feature,需要在Cargo.toml里开启对应的依赖配置。
修复步骤
首先修改Cargo.toml依赖配置,开启TLS支持:
[dependencies] ws = { version = "0.9", features = ["ssl"] }
Handler写法修复版
extern crate ws; use ws::{connect, Handler, Sender, Handshake, Result, Message}; struct Client { out: Sender, } impl Handler for Client { fn on_open(&mut self, _: Handshake) -> Result<()> { // 连接握手完成后再发送认证和监听请求 self.out.send(r#"{"action": "authenticate","data": {"key_id": "<API_KEY>","secret_key": "<API_SECRET>"}}"#)?; self.out.send(r#"{"action": "listen","data": {"streams": ["AM.SPY"]}}"#) } fn on_message(&mut self, msg: Message) -> Result<()> { println!("message: {}", msg); Ok(()) } fn on_error(&mut self, err: ws::Error) { // 加上错误回调方便排查问题 eprintln!("WebSocket error: {:?}", err); } } fn main() { // 客户端用connect,不要用listen if let Err(error) = connect("wss://data.alpaca.markets/stream", |out| { Client { out } }) { println!("Failed to create WebSocket due to: {:?}", error); } }
闭包写法修复版
如果你偏好闭包写法,修复后的代码如下:
extern crate ws; use ws::{connect, Message, Result}; fn main() { if let Err(error) = connect("wss://data.alpaca.markets/stream", |out| { // 统一处理连接事件,和JS的事件监听逻辑对齐 move |event| { match event { ws::Event::Open(_) => { // 连接打开后再发消息 if out.send(r#"{"action": "authenticate","data": {"key_id": "<API_KEY>","secret_key": "<API_SECRET>"}}"#).is_err() { println!("Websocket couldn't queue authenticate message.") }; if out.send(r#"{"action": "listen","data": {"streams": ["AM.SPY"]}}"#).is_err() { println!("Websocket couldn't queue listen message.") }; } ws::Event::Message(msg) => { println!("message: '{}'. ", msg); } ws::Event::Error(err) => { eprintln!("Error: {:?}", err); } _ => {} } Ok(()) } }) { println!("Failed to create WebSocket due to: {:?}", error); } }
内容的提问来源于stack exchange,提问作者Loading
相关产品推荐
相关产品推荐

