https://github.com/black-binary/async-smux
A lightweight asynchronous smux multiplexing library
https://github.com/black-binary/async-smux
async async-smux async-std rust smol smux
Last synced: 21 days ago
JSON representation
A lightweight asynchronous smux multiplexing library
- Host: GitHub
- URL: https://github.com/black-binary/async-smux
- Owner: black-binary
- License: mit
- Created: 2020-10-14T04:49:35.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2025-04-25T15:51:55.000Z (about 1 year ago)
- Last Synced: 2025-04-25T16:50:45.819Z (about 1 year ago)
- Topics: async, async-smux, async-std, rust, smol, smux
- Language: Rust
- Homepage:
- Size: 114 KB
- Stars: 57
- Watchers: 2
- Forks: 19
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# async-smux
[crates.io](https://crates.io/crates/async_smux)
A lightweight asynchronous [smux](https://github.com/xtaci/smux) (Simple MUltipleXing) library for smol/async-std and any async runtime compatible to `futures`.

`async-smux` consumes a struct implementing `AsyncRead + AsyncWrite + Unpin + Send`, like `TcpStream` and `TlsStream`, to create a `Mux` struct. And then you may spawn multiple `MuxStream`s (up to 4294967295) over `Mux`, 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 `future`s. So it's totally 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.
## Specification
```text
VERSION(1B) | CMD(1B) | LENGTH(2B) | STREAMID(4B) | DATA(LENGTH)
VERSION: 1
CMD:
SYN(0)
FIN(1)
PSH(2)
NOP(3)
STREAMID: Randomly chosen number
```
## Example
```rust
use async_smux::{Mux, MuxConfig};
use async_std::net::{TcpListener, TcpStream};
use async_std::prelude::*;
async fn echo_server() {
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 mux_stream = mux.accept().await.unwrap();
let mut buf = [0u8; 1024];
let size = mux_stream.read(&mut buf).await.unwrap();
mux_stream.write(&buf[..size]).await.unwrap();
}
}
fn main() {
async_std::task::spawn(echo_server());
async_std::task::block_on(async {
smol::Timer::after(std::time::Duration::from_secs(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 mux_stream = mux.connect().await.unwrap();
let mut buf = [0u8; 1024];
mux_stream.write(b"hello").await.unwrap();
let size = mux_stream.read(&mut buf).await.unwrap();
let reply = String::from_utf8(buf[..size].to_vec()).unwrap();
println!("{}: {}", i, reply);
}
});
}
```