WebSocket libraries in Rust: tokio-tungstenite and async-tungstenite
WebSocket is a protocol that provides two-way communication between a client and a server over a single TCP connection. In the Rust ecosystem, two main libraries are used for working with WebSocket: tokio-tungstenite (asynchronous, based on Tokio) and async-tungstenite (asynchronous, but with support for different runtimes). Both are built on top of the low-level library tungstenite, which implements the WebSocket protocol itself.
Why use WebSocket in Rust?
Rust is a systems language that is ideal for creating high-load network applications. WebSocket libraries in Rust allow you to:
- Create chats, games, and real-time notification systems
- Handle thousands of concurrent connections with minimal memory consumption
- Use Rust's memory safety at the compilation level
- Integrate with other asynchronous libraries (e.g., with HTTP servers)
Installation and setup
Add the dependency to Cargo.toml:
[dependencies]tokio = { version = "1", features = ["full"] }tokio-tungstenite = "0.21"futures-util = "0.3"For async-tungstenite:
[dependencies]async-tungstenite = "0.25"async-std = "1.12"Creating a WebSocket client in Rust
Example of a simple client that connects to a server and sends a message:
use futures_util::{SinkExt, StreamExt};use tokio_tungstenite::{connect_async, tungstenite::Message};
#[tokio::main]async fn main() { let url = "wss://echo.websocket.org"; let (mut ws_stream, _) = connect_async(url).await.expect("Connection error");
println!("Connected to server");
// Send a message ws_stream.send(Message::Text("Hello, WebSocket!".into())).await.unwrap();
// Receive a response if let Some(msg) = ws_stream.next().await { let msg = msg.unwrap(); if let Message::Text(text) = msg { println!("Received: {}", text); } }
ws_stream.close(None).await.unwrap();}Creating a WebSocket server in Rust
A server that accepts connections and echo responses:
use tokio::net::TcpListener;use tokio_tungstenite::accept_async;use futures_util::{SinkExt, StreamExt};use tokio_tungstenite::tungstenite::Message;
#[tokio::main]async fn main() { let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); println!("Server started on ws://127.0.0.1:8080");
while let Ok((stream, addr)) = listener.accept().await { tokio::spawn(async move { println!("New connection: {}", addr);
let ws_stream = accept_async(stream).await.unwrap(); let (mut sender, mut receiver) = ws_stream.split();
while let Some(msg) = receiver.next().await { match msg { Ok(Message::Text(text)) => { println!("Message from {}: {}", addr, text); sender.send(Message::Text(format!("Echo: {}", text))).await.unwrap(); } Ok(Message::Close(_)) => break, _ => {} } }
println!("Connection with {} closed", addr); }); }}Main features of the libraries
- TLS/SSL support — secure connections via WSS (requires enabling the
tlsfeature) - Automatic reconnection — can be implemented using loops and timers
- Ping/pong frames — for maintaining the connection
- Binary messages — working with
Message::Binary
Also in library
Working with XML in PHP: A Complete Guide to Parsing and Creating XML Documents
MSW for TypeScript: Complete Guide with Examples
Logging in Kotlin: Best Libraries and Tools for Development
MailKit for C# (.NET): Complete Guide with Examples