High performance, strict, tokio-util based websockets implementation.
Uri
from http
in the clientBytes
as payload storageFeature flags in tokio-websockets are added to allow tailoring it to your needs.
simd
will enable AVX2 and SSE2 accelerated masking and UTF-8 validationclient
enables a tiny client implementationserver
enables a tiny server implementationhttp-integration
enables a method for websocket upgrade http::Request
generationTLS support is supported via any of the following feature flags:
native-tls
for a tokio-native-tls
backed implementationrustls-webpki-roots
for a tokio-rustls
backed implementation with webpki-roots
rustls-native-roots
for a tokio-rustls
backed implementation with rustls-native-certs
One SHA1 implementation is required, usually provided by the TLS implementation:
ring
is used if rustls
is the TLS libraryopenssl
feature will use openssl
, usually prefered on most Linux/BSD systems with native-tls
sha1_smol
feature can be used as a fallback if no TLS is neededThe client
feature requires enabling one random number generator:
fastrand
is the default used and a PRNG
getrandom
can be used as a cryptographically secure RNGrand
can be used as an alternative to fastrand
and should be preferred if it is already in the dependency treeFor these reasons, I recommend disabling default features and using a configuration that makes sense for you, for example:
```toml
tokio-websockets = { version = "*", default-features = false, features = ["client", "fastrand", "sha1_smol"] }
tokio-websockets = { version = "*", default-features = false, features = ["client", "getrandom", "simd", "rustls-webpki-roots"] } ```
This is a simple websocket echo server without any proper error handling.
More examples can be found in the examples folder.
```rust use futuresutil::SinkExt; use http::Uri; use tokio::net::TcpListener; use tokiowebsockets::{ClientBuilder, Error, Message, ServerBuilder};
async fn main() -> Result<(), Error> { let listener = TcpListener::bind("127.0.0.1:3000").await?;
tokio::spawn(async move { while let Ok((stream, )) = listener.accept().await { let mut wsstream = ServerBuilder::new() .accept(stream) .await?;
tokio::spawn(async move {
// Just an echo server, really
while let Some(Ok(msg)) = ws_stream.next().await {
if msg.is_text() || msg.is_binary() {
ws_stream.send(msg).await?;
}
}
Ok::<_, Error>(())
});
}
Ok::<_, Error>(())
});
let uri = Uri::fromstatic("ws://127.0.0.1:3000"); let mut client = ClientBuilder::fromuri(uri).connect().await?;
client.send(Message::text(String::from("Hello world!"))).await?;
while let Some(Ok(msg)) = client.next().await { if let Ok(text) = msg.astext() { asserteq!(text, "Hello world!"); // We got one message, just stop now client.close(None, None).await?; } }
Ok(()) } ```
Currently, WebsocketStream
does not implement Stream
due to the poll_next
nature of the trait, which makes implementing it with actual async code near impossible.
I am waiting for async traits and will implement it once possible. Until then, a method called next
already exists and serves as a replacement for futures-util's next
, which most users were probably looking for.
Further, websocket compression is currently unsupported.