Tokio Tungstenite WebSocket Split
Split a WebSocket stream into independent sink and stream halves, running concurrent send and receive loops with heartbeats.
Code
use futures_util::{SinkExt, StreamExt};
use tokio_tungstenite::{connect_async, tungstenite::Message};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (ws_stream, _response) = connect_async("wss://stream.example.com/feed").await?;
// 拆分为独立的读半与写半:两个方向并发推进互不阻塞
let (mut write, mut read) = ws_stream.split();
let mut heartbeat = tokio::time::interval(std::time::Duration::from_secs(25));
let mut received = 0usize;
loop {
tokio::select! {
// 读方向:服务器推送的消息
msg = read.next() => {
match msg {
Some(Ok(Message::Text(text))) => {
received += 1;
println!("recv: {} bytes", text.len());
}
Some(Ok(Message::Ping(ping))) => {
// 协议层心跳:自动回 pong
write.send(Message::Pong(ping)).await?;
}
Some(Ok(_)) => {}
Some(Err(err)) => return Err(err.into()),
None => break, // 服务器关闭连接
}
}
// 写方向:应用层心跳与订阅指令
_ = heartbeat.tick() => {
write.send(Message::Text(r#"{"op":"ping"}"#.into())).await?;
}
}
if received >= 5 {
break;
}
}
write.send(Message::Close(None)).await?;
println!("received {received} messages");
Ok(())
}Report a problem with this exampleOpens a pre-filled issue on GitHub.