用 Rust + Actix-Web 打造“Hello, WebSocket!”——從握手到回聲,只需 50 行代碼
一、為什么選擇 Rust 寫 WebSocket?
- 零成本抽象:編譯期確定生命周期,無 GC 抖動,延遲低至微秒級
- actix-web:Tokio 生態最成熟的 Web 框架,單機輕松扛 100k 并發
- 類型安全:消息格式一旦定義,編譯器幫你杜絕“字段對不上”的運行時崩潰
二、核心代碼逐行拆解
下面這份 echo
處理器就是全部業務邏輯——沒有魔法,只有 Rust 標準流程:
pub async fn echo(req: HttpRequest, // HTTP 升級握手請求stream: web::Payload, // 原始 TCP 字節流
) -> Result<HttpResponse, Error> {// 1. 協議升級:返回 101 Switching Protocolslet (res, mut session, stream) = actix_ws::handle(&req, stream)?;// 2. 消息聚合:把可能分片的 WebSocket 幀拼成完整消息let mut stream = stream.aggregate_continuations().max_continuation_size(2_usize.pow(20)); // 1 MiB 上限// 3. 異步任務:在后臺持續讀寫,不阻塞主線程rt::spawn(async move {while let Some(msg) = stream.next().await {match msg {Ok(AggregatedMessage::Text(text)) => {println!("↑ {}", text);session.text(text).await.unwrap(); // 原樣回聲}Ok(AggregatedMessage::Binary(bin)) => {println!("↑ (bin) {:x?}", bin);session.binary(bin).await.unwrap();}Ok(AggregatedMessage::Ping(p)) => {println!("↑ ping");session.pong(&p).await.unwrap(); // 保活}_ => {} // Close/Pong 直接忽略}}});Ok(res) // 4. 立即返回 101,升級完成
}
三、把 WebSocket 掛到路由表
在 config_routes
里加一行即可:
web::scope("/ws").route("", web::get().to(echo))
前端連接示例:
const ws = new WebSocket('ws://localhost:8080/api/ws');
ws.onmessage = (ev) => console.log('↓', ev.data);
ws.send('Hello Rust!');
四、性能小貼士
- 零拷貝:
session.text(text)
直接借用String
,無需額外克隆 - 背壓保護:
max_continuation_size
限制單消息大小,防內存炸彈 - 任務隔離:
rt::spawn
讓每條連接獨立調度,互不影響
五、下一步?
- 用
broadcast
頻道實現聊天室 - 用
serde
把 JSON 消息強類型化 - 用
rustls
升級成wss
安全連接
完整項目已上傳 GitHub,克隆即可跑:
git clone https://github.com/your-name/actix-ws-echo
cd actix-ws-echo && cargo run
打開瀏覽器,WebSocket 握手→回聲,只需一次 cargo run
,你就擁有了毫秒級延遲的實時通信后端。Enjoy Rust!