掌握Rust WebSocket编程:实时通信、消息协议和连接管理。
// Cargo.toml: tokio-tungstenite, futures-util
use tokio::net::TcpListener;
use tungstenite::Message;
use futures_util::{StreamExt, SinkExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
println!("WebSocket服务端监听 :8080");
while let Ok((stream, addr)) = listener.accept().await {
tokio::spawn(async move {
let ws_stream = tokio_tungstenite::accept_async(stream).await.unwrap();
println!("WebSocket连接: {}", addr);
let (mut write, mut read) = ws_stream.split();
while let Some(msg) = read.next().await {
let msg = msg.unwrap();
if msg.is_text() || msg.is_binary() {
write.send(msg).await.unwrap();
}
}
});
}
Ok(())
}
✅ 编译验证通过
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum WsMessage {
Chat { from: String, text: String },
Join { name: String },
Leave { name: String },
Pong,
}
// 编码
fn encode(msg: &WsMessage) -> Message {
Message::text(serde_json::to_string(msg).unwrap())
}
// 解码
fn decode(msg: &Message) -> Option<WsMessage> {
serde_json::from_str(msg.to_text().ok()?).ok()
}
use tokio::sync::broadcast;
async fn chat_room(stream: tokio::net::TcpStream, tx: broadcast::Sender<String>) {
let ws = tokio_tungstenite::accept_async(stream).await.unwrap();
let (mut write, mut read) = ws.split();
let mut rx = tx.subscribe();
loop {
tokio::select! {
msg = read.next() => {
if let Some(Ok(msg)) = msg {
let _ = tx.send(msg.to_string());
} else { break; }
}
msg = rx.recv() => {
if let Ok(text) = msg {
let _ = write.send(Message::text(text)).await;
}
}
}
}
}
| 特性 | HTTP | WebSocket |
|---|---|---|
| 方向 | 请求-响应 | 双向 |
| 开销 | 每请求完整头 | 升级后极小 |
| 实时性 | 需轮询 | 服务端推送 |
| 适用 | CRUD | 聊天、游戏、实时数据 |
实现WebSocket的Ping/Pong心跳保活。
实现多房间的聊天服务器。
用二进制WebSocket帧传输结构化数据。
掌握WebSocket——实时双向通信
Rust的异步模型与其他语言有本质区别:
async函数不是语法糖生成闭包或Future对象,而是编译器生成一个状态机enum,每个.await点是一个状态。这比Green Thread更高效——无堆分配、无运行时开销。
不使用的异步特性不产生代码。不调用async函数?没有状态机代码。这与其他语言的全局运行时(Go的goroutine调度器、Java的Fiber)不同。
Rust没有内置异步运行时。你选择Tokio、async-std或其他——运行时是库,不是语言特性。这意味着灵活但需要选择。
| 模型 | 语言 | 开销 | 并发数 |
|---|---|---|---|
| OS线程 | C/Java | 1-8MB/线程 | ~1000 |
| Green Thread | Go | ~2KB/goroutine | ~100K |
| async/await | Rust | ~几百字节 | ~1M+ |
| 回调 | Node.js | 小 | 高 |
以下练习帮助你将本课知识应用到实际场景:
阅读以下代码片段,找出潜在问题并改进:
// 仔细阅读,思考有什么问题
fn process(data: Vec) -> Vec {
let mut result = Vec::new();
for i in 0..data.len() {
result.push(data[i] * 2);
}
result
}
改进建议:使用迭代器、预分配容量、考虑溢出。
用criterion基准测试对比以下实现的性能差异:
为以下场景设计Rust API:一个支持过期时间的缓存系统。考虑所有权、错误处理和泛型。
通过本课的学习,你应该掌握以下核心要点:
如果某个要点还不够清晰,回顾本课的代码示例和内存图,动手编写代码验证你的理解。
以下资源帮助你深入学习本课主题:
本课涉及的核心概念,确保你理解每一个:
| 术语 | 说明 |
|---|---|
| 所有权 | Rust内存管理的核心机制,每个值有唯一所有者 |
| 借用 | 通过引用访问数据,不获取所有权 |
| 生命周期 | 引用有效的范围,编译期分析工具 |
| trait | Rust的接口/抽象机制,类似其他语言的接口 |
| 泛型 | 参数化类型,零成本抽象 |
| 模式匹配 | 强大的数据解构和分支机制 |
| 零成本抽象 | 高层抽象不引入运行时开销 |
| fearless concurrency | 编译器保证线程安全 |
Q: Rust学习曲线真的很陡吗?
A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。
Q: Rust适合什么项目?
A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。
Q: 遇到编译错误怎么办?
A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。