High performance, strict, tokio-util based websockets implementation.
This crate has not been tested enough to an extent that I would deem it ready for usage in production enviroments of big projects. Try it before deploying and please give feedback!
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 http::Request
upgrade 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 neededFor 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", "sha1_smol"] }
tokio-websockets = { version = "*", default-features = false, features = ["client", "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.