Rust WebSocket Libraries: Tokio-tungstenite and async-tungstenite for Real-Time

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Rust WebSocket Libraries: Tokio-tungstenite and async-tungstenite



In modern web development, the WebSocket protocol has become the standard for creating real-time applications: chats, online games, financial tickers, and notification systems. The Rust ecosystem offers powerful and safe tools for working with WebSockets, among which tokio-tungstenite and async-tungstenite stand out. These libraries are built on top of the popular Tokio asynchronous runtime and the high-performance tungstenite WebSocket stack.



What are Tokio-tungstenite and async-tungstenite?



Tokio-tungstenite is an asynchronous WebSocket library for Rust, integrated with the Tokio runtime. It provides convenient abstractions for creating WebSocket servers and clients using standard Tokio types (TcpListener, TcpStream).



Async-tungstenite is a more general version that works with any asynchronous runtime (Tokio, async-std, smol) via the AsyncRead and AsyncWrite traits. Both libraries provide full support for RFC 6455, including message fragmentation, ping/pong, and masking.



Key Features

  • Asynchronous — non-blocking operations using async/await
  • High Performance — minimal overhead thanks to zero-copy parsing
  • Type Safety — messages are represented as strictly typed structures
  • Flexibility — support for both server and client sides
  • SSL/TLS — built-in support for secure connections via rustls or native-tls
  • Automatic Connection Management — handling disconnections and reconnections


Installation

Add to Cargo.toml:

[dependencies]tokio = { version = "1", features = ["full"] }tokio-tungstenite = "0.21"futures-util = "0.3"


Example: WebSocket Server

Let's create a simple echo server that sends back the received message:

use tokio::net::TcpListener;use tokio_tungstenite::accept_async;use futures_util::{SinkExt, StreamExt};use std::error::Error;

#[tokio::main]async fn main() -> Result<(), Box> { let listener = TcpListener::bind("127.0.0.1:8080").await?; println!("WebSocket server started on ws://127.0.0.1:8080");

while let Ok((stream, addr)) = listener.accept().await { println!("New connection: {}", addr); tokio::spawn(handle_connection(stream)); } Ok(())}

async fn handle_connection(stream: tokio::net::TcpStream) { let ws_stream = accept_async(stream).await.expect("Handshake error"); let (mut write, mut read) = ws_stream.split();

while let Some(Ok(msg)) = read.next().await { if msg.is_text() || msg.is_binary() { // Send the message back if let Err(e) = write.send(msg).await { eprintln!("Send error: {}", e); break; } } } println!("Connection closed");}


Example: WebSocket Client

Connect to the server and send a greeting:

use tokio_tungstenite::connect_async;use futures_util::{SinkExt, StreamExt};use url::Url;

#[tokio::main]async fn main() -> Result<(), Box> { let url = Url::parse("ws://127.0.0.1:8080")?; let (ws_stream, _) = connect_async(url).await?; println!("Connected to server");

let (mut write, mut read) = ws_stream.split();

// Send a message write.send("Hello, world!".into()).await?; println!("Sent: Hello, world!");

// Read the response if let S

Recommendations