async-smux

crates.io

A lightweight asynchronous smux (Simple MUltipleXing) library for smol/async-std and any async runtime compatible to futures.

img

async-smux consumes a struct implementing AsyncRead + AsyncWrite + Unpin + Send, like TcpStream and TlsStream. And then you may spawn multiple MuxStreams(up to 65535), which also implements AsyncRead + AsyncWrite + Unpin + Send.

Benchmark

Here is a simple benchmarking result on my local machine, comparing to the original version smux (written in go).

| Implementation | Throughput (TCP) | Handshake | | ----------------- | ---------------- | ---------- | | smux (go) | 0.4854 GiB/s | 17.070 K/s | | async-smux (rust) | 1.0550 GiB/s | 81.774 K/s |

Run cargo bench to test it by yourself. Check out /benches directory for more details.

Laziness

No thread or task will be spawned by this library. It just spawns a few futures. So it's runtime-independent.

Mux and MuxStream are completely lazy and will DO NOTHING if you don't poll() them.

Any polling operation, including .read() ,.write(), accept() and connect(), will push Mux and MuxStream working.

Example

```rust use asyncsmux::{Mux, MuxConfig}; use asyncstd::net::{TcpListener, TcpStream}; use async_std::prelude::*;

async fn echoserver() { let listener = TcpListener::bind("0.0.0.0:12345").await.unwrap(); let (stream, _) = listener.accept().await.unwrap(); let mux = Mux::new(stream, MuxConfig::default()); loop { let mut muxstream = mux.accept().await.unwrap(); let mut buf = [0u8; 1024]; let size = muxstream.read(&mut buf).await.unwrap(); muxstream.write(&buf[..size]).await.unwrap(); } }

fn main() { asyncstd::task::spawn(echoserver()); asyncstd::task::blockon(async { smol::Timer::after(std::time::Duration::fromsecs(1)).await; let stream = TcpStream::connect("127.0.0.1:12345").await.unwrap(); let mux = Mux::new(stream, MuxConfig::default()); for i in 0..100 { let mut muxstream = mux.connect().await.unwrap(); let mut buf = [0u8; 1024]; muxstream.write(b"hello").await.unwrap(); let size = muxstream.read(&mut buf).await.unwrap(); let reply = String::fromutf8(buf[..size].tovec()).unwrap(); println!("{}: {}", i, reply); } }); } ```