Bibliotecas WebSocket para Rust: tungstenite e tokio-tungstenite
WebSocket é um protocolo que fornece comunicação full-duplex entre cliente e servidor sobre uma única conexão TCP. No ecossistema Rust, as bibliotecas mais populares para trabalhar com WebSocket são tungstenite (síncrona) e tokio-tungstenite (assíncrona baseada em Tokio). Ambas as bibliotecas fornecem uma API de alto nível para criar servidores e clientes WebSocket, suportam extensões padrão e segurança via TLS.
Principais funcionalidades
- tungstenite: implementação síncrona do WebSocket (RFC 6455), suporta operações bloqueantes, adequada para scripts simples e incorporação.
- tokio-tungstenite: wrapper assíncrono sobre tungstenite, integra-se com o runtime Tokio, permite processar milhares de conexões simultaneamente.
- Suporte a frames, mensagens, pings/pongs, fechamento de conexão.
- Trabalho com TLS (através de
rustlsounative-tls). - Suporte a extensões WebSocket (por exemplo, compressão permessage-deflate).
- Configuração simples e dependências mínimas.
Instalação
Adicione a biblioteca ao Cargo.toml:
[dependencies]tokio-tungstenite = "0.21" # variante assíncronatungstenite = "0.21" # variante síncronatokio = { version = "1", features = ["full"] } # para tokio-tungsteniteExemplo de servidor WebSocket assíncrono (tokio-tungstenite)
Vamos criar um simples servidor echo que recebe mensagens de texto e as envia de volta:
use tokio::net::TcpListener;use tokio_tungstenite::accept_async;use tokio_tungstenite::tungstenite::Message;use futures_util::{SinkExt, StreamExt};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let listener = TcpListener::bind("127.0.0.1:9001").await?; println!("Servidor WebSocket iniciado em ws://127.0.0.1:9001");
while let Ok((stream, peer)) = listener.accept().await { tokio::spawn(handle_connection(stream, peer)); } Ok(())}
async fn handle_connection(stream: tokio::net::TcpStream, peer: std::net::SocketAddr) { let ws_stream = match accept_async(stream).await { Ok(ws) => ws, Err(e) => { eprintln!("Erro ao conectar {}: {}", peer, e); return; } };
let (mut write, mut read) = ws_stream.split(); println!("Nova conexão: {}", peer);
while let Some(msg) = read.next().await { match msg { Ok(Message::Text(text)) => { println!("Recebido de {}: {}", peer, text); if let Err(e) = write.send(Message::Text(text.into())).await { eprintln!("Erro ao enviar: {}", e); break; } } Ok(Message::Close(_)) => { println!("Cliente {} desconectado", peer); break; } Err(e) => { eprintln!("Erro: {}", e); break; } _ => {} // Ignoramos mensagens binárias e de controle } }}Exemplo de cliente WebSocket síncrono (tungstenite)
Um cliente simples que se conecta ao servidor e envia uma mensagem:
use tungstenite::{connect, Message};use url::Url;
fn main() -> Result<(), Box<dyn std::error::Error>> { let url = Url::parse("ws://echo.websocket.org")?; let (mut socket, response) = connect(url)?;
println!("Conectado ao servidor"); println!("Status HTTP: {}", response.status());
socket.send(Message::Text("Olá, WebSocket!".into()))?; println!("Mensagem enviada");
let msg = socket.read()?; if let Message::T Também na biblioteca
Diesel para Rust: guia completo com exemplos
Geração Swagger/OpenAPI para C++: melhores ferramentas e bibliotecas
Trabalho com S3 e armazenamentos em nuvem em Java: AWS SDK e MinIO
Trabalho com imagens em C++: bibliotecas CImg e STB Image
Trabalhando com S3 e armazenamento em nuvem em JavaScript (Node.js) — biblioteca @aws-sdk/client-s3