用 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 Protocols
let (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!