掌握Rust异步TCP编程:服务端、客户端、协议解析和连接管理。
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
println!("服务端监听 127.0.0.1:8080");
loop {
let (mut socket, addr) = listener.accept().await?;
println!("新连接: {}", addr);
tokio::spawn(async move {
let mut buf = [0; 1024];
loop {
let n = match socket.read(&mut buf).await {
Ok(0) => return,
Ok(n) => n,
Err(e) => { println!("读错误: {}", e); return; }
};
if let Err(e) = socket.write_all(&buf[..n]).await {
println!("写错误: {}", e); return;
}
}
});
}
}
✅ 编译验证通过
use tokio::net::TcpStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.write_all(b"Hello!").await?;
let mut buf = [0; 1024];
let n = stream.read(&mut buf).await?;
println!("收到: {:?}", &buf[..n]);
Ok(())
}
✅ 编译验证通过
use tokio::io::{AsyncBufReadExt, BufReader};
// 行协议:每行一个命令
async fn handle_connection(stream: tokio::net::TcpStream) {
let (reader, mut writer) = stream.into_split();
let mut reader = BufReader::new(reader);
let mut line = String::new();
loop {
line.clear();
match reader.read_line(&mut line).await {
Ok(0) => break, // EOF
Ok(_) => {
let cmd = line.trim();
let response = match cmd {
"PING" => "PONG",
"INFO" => "Rust TCP Server v1.0",
s if s.starts_with("ECHO ") => &s[5..],
_ => "ERROR: 未知命令",
};
writer.write_all(format!("{}\n", response).as_bytes()).await.unwrap();
}
Err(e) => { println!("错误: {}", e); break; }
}
}
}
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
#[tokio::main]
async fn main() {
let listener = TcpListener::bind("0.0.0.0:8080").await.unwrap();
let connections = Arc::new(AtomicUsize::new(0));
loop {
let (socket, addr) = listener.accept().await.unwrap();
let conn_count = Arc::clone(&connections);
conn_count.fetch_add(1, Ordering::Relaxed);
tokio::spawn(async move {
handle_connection(socket).await;
conn_count.fetch_sub(1, Ordering::Relaxed);
});
}
}
用broadcast通道实现多人聊天室。
实现4字节长度前缀的二进制协议。
实现简单的TCP代理转发。
掌握TCP异步编程——构建网络服务的基础
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 | 小 | 高 |
以下资源帮助你深入学习本课主题:
本课涉及的核心概念,确保你理解每一个:
| 术语 | 说明 |
|---|---|
| 所有权 | Rust内存管理的核心机制,每个值有唯一所有者 |
| 借用 | 通过引用访问数据,不获取所有权 |
| 生命周期 | 引用有效的范围,编译期分析工具 |
| trait | Rust的接口/抽象机制,类似其他语言的接口 |
| 泛型 | 参数化类型,零成本抽象 |
| 模式匹配 | 强大的数据解构和分支机制 |
| 零成本抽象 | 高层抽象不引入运行时开销 |
| fearless concurrency | 编译器保证线程安全 |
Q: Rust学习曲线真的很陡吗?
A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。
Q: Rust适合什么项目?
A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。
Q: 遇到编译错误怎么办?
A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。