A high-performance WebSocket client for the monoio async runtime. It dials both ws:// and wss:// endpoints, performs the HTTP upgrade handshake, and hands you a fully configured [fastwebsockets::WebSocket] client stream.
Note: Documentation is AI generated.
- Monoio-first: Uses
io_uringon Linux via monoio for low-latency networking. - TLS out of the box:
wss://connections usemonoio-rustlswith the Mozilla root store. - Zero-copy friendly: Frame writes avoid intermediate allocations whenever possible.
- Safe defaults: Auto close and auto pong are enabled; TLS writev is disabled for compatibility.
- Minimal surface area: One
WsClient::connecthelper plus re-exported stream types if you want lower-level control.
Add the crate and its companion dependencies to your project:
[dependencies]
websockets-monoio = "0.1.1"
monoio = "0.2"
fastwebsockets = "0.10"
anyhow = "1.0"The crate targets Rust 1.90.0 or newer (see Cargo.toml).
use fastwebsockets::{Frame, OpCode};
use websockets_monoio::WsClient;
#[monoio::main]
async fn main() -> anyhow::Result<()> {
let mut client = WsClient::connect("wss://echo.websocket.org/", &[]).await?;
client
.ws
.write_frame(Frame::text("Hello, WebSocket!".as_bytes().into()))
.await?;
let frame = client.ws.read_frame().await?;
if let OpCode::Text = frame.opcode {
println!("Received: {}", std::str::from_utf8(&frame.payload)?);
}
Ok(())
}use fastwebsockets::{Frame, OpCode};
use websockets_monoio::WsClient;
#[monoio::main]
async fn main() -> anyhow::Result<()> {
let mut client =
WsClient::connect("wss://stream.binance.com:9443/ws/btcusdt@trade", &[]).await?;
let subscribe = r#"{"method":"SUBSCRIBE","params":["btcusdt@trade"],"id":1}"#;
client
.ws
.write_frame(Frame::text(subscribe.as_bytes().into()))
.await?;
loop {
let frame = client.ws.read_frame().await?;
match frame.opcode {
OpCode::Text => println!("{}", std::str::from_utf8(&frame.payload)?),
OpCode::Binary => println!("Binary frame ({} bytes)", frame.payload.len()),
OpCode::Close => break,
_ => {}
}
}
Ok(())
}use websockets_monoio::WsClient;
#[monoio::main]
async fn main() -> anyhow::Result<()> {
let client = WsClient::connect(
"wss://api.example.com/socket",
&[
("Authorization", "Bearer your-token"),
("User-Agent", "your-app/1.0"),
],
)
.await?;
// Use client.ws ...
drop(client);
Ok(())
}Further examples live in examples/:
cargo run --example echo_clientcargo run --example crypto_stream
WsClient::connect(url, extra_headers)performs DNS resolution, TCP/TLS setup, and the HTTP upgrade handshake before returning aWebSocket<WsStream>.WsClient::into_inner()gives direct access to the underlyingfastwebsockets::WebSocket.WsStreamis the enum used by the client (PlainTCP orTlsover TCP). It implementsmonoio_compat::AsyncReadandAsyncWrite.- Supporting modules such as
http_upgrade,tls, andurlare re-exported for advanced use-cases if you want to build your own handshake flow.
Errors from WsClient::connect use anyhow::Result, allowing full context while still being compatible with other error handling strategies.
Benchmarks live in benches/perf.rs and run locally without external services. Launch them with:
cargo benchWhat you get:
connect/ws_connectmeasures full handshake latency against an in-process monoio echo server.round_trip/*tests send-and-receive latency for text and binary frames of varying sizes.
Results depend on kernel support for io_uring; Linux 5.1+ is recommended for representative numbers.
- Linux: Full support with
io_uring. This is the primary target. - macOS / Windows: Works via monoio’s fallback driver, but without
io_uringoptimisations.
TLS connections use rustls with the Mozilla CA bundle (webpki-roots). A global TlsConnector is reused across calls to keep setup cheap.
Issues and PRs are welcome. By contributing you agree to license your work under MIT OR Apache-2.0, the same as the rest of the project.
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.