Rust 多线程和网络编程
一、综合示例
1、效果展示
2、源码分享
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::thread;
fn handle_client(mut stream: TcpStream) {
let mut buffer = [0; 512];
loop {
match stream.read(&mut buffer) {
Ok(size) => {
if size == 0 {
// Connection closed
println!("Client disconnected: {}", stream.peer_addr().unwrap());
break;
}
stream.write(&buffer[0..size]).unwrap();
}
Err(e) => {
println!("Error: {}", e);
break;
}
}
}
}
fn main() {
let lis = TcpListener::bind("127.0.0.1:12345").unwrap();
for stream in lis.incoming() {
match stream {
Ok(stream) => {
println!("Client connected: {}", stream.peer_addr().unwrap());
thread::spawn(move || {
handle_client(stream);
});
}
Err(e) => {
eprintln!("Error: {}", e);
}
}
}
}
二、多线程
Rust 通过所有权机制和类型系统,在编译期即可避免数据竞争,实现安全高效的多线程编程。以下从核心概念到实践逐步解析:
1、线程创建
使用 std::thread::spawn
创建新线程,返回 JoinHandle
用于等待线程结束:
use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("子线程运行中!");
});
handle.join().unwrap(); // 等待子线程结束
println!("主线程结束");
}
2、线程间通信
通道(Channel) 是消息传递的核心工具,基于生产者-消费者模型:
use std::sync::mpsc; // 多生产者单消费者
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send("子线程消息".to_string()).unwrap();
});
println!("收到: {}", rx.recv().unwrap());
}
mpsc::channel()
创建通道tx.send()
发送数据rx.recv()
阻塞接收数据
3、共享状态并发
互斥锁(Mutex) 保护共享数据:
use std::sync::{Mutex, Arc};
fn main() {
let counter = Arc::new(Mutex::new(0)); // 原子引用计数包装
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1; // 修改共享数据
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("最终值: {}", *counter.lock().unwrap());
}
Arc<T>
实现多线程安全引用计数Mutex::lock()
获取锁,保证独占访问
4、高级同步原语
- 屏障(Barrier):协调多个线程同时到达某点
use std::sync::{Arc, Barrier}; let barrier = Arc::new(Barrier::new(3)); // 等待3个线程
- 条件变量(Condvar):与互斥锁配合实现复杂同步
let pair = Arc::new((Mutex::new(false), Condvar::new()));
5、原子操作
对简单类型使用原子变量避免锁开销:
use std::sync::atomic::{AtomicUsize, Ordering};
let count = AtomicUsize::new(0);
count.fetch_add(1, Ordering::SeqCst); // 原子递增
Ordering
指定内存顺序(如Relaxed
,Acquire
,Release
)
6、线程池实践
使用 rayon
库实现高效并行迭代:
# Cargo.toml
[dependencies]
rayon = "1.7"
use rayon::prelude::*;
fn main() {
let v = vec![1, 2, 3, 4];
v.par_iter().for_each(|n| println!("{}", n)); // 自动线程池
}
关键特性对比
机制 | 适用场景 | 优势 |
---|---|---|
通道 | 任务流水线 | 零共享数据,避免锁竞争 |
互斥锁 | 复杂共享状态 | 数据修改灵活 |
原子操作 | 计数器/标志位 | 无锁,高性能 |
线程池 | 批量任务处理 | 自动负载均衡 |
安全原则
- 编译期检查:所有权系统强制要求:
- 跨线程传递的数据必须实现
Send
trait(表示可安全转移所有权) - 共享引用需实现
Sync
trait(表示可安全跨线程共享)
- 跨线程传递的数据必须实现
- 错误预防:常见问题如死锁仍需开发者注意,可通过
MutexGuard
作用域限定锁周期
三、网络编程
Rust 凭借其内存安全、零成本抽象和高性能特性,成为网络编程的理想选择。以下是核心概念与实现步骤:
1、Rust 网络编程基础
- 核心库:
std::net
提供同步网络操作(TCP/UDP)。 - 异步运行时:
tokio
或async-std
实现非阻塞 I/O(推荐)。 - 关键协议:
- TCP:可靠流式传输(如 HTTP/WebSocket)。
- UDP:低延迟数据报传输(如 DNS/游戏协议)。
2、同步 TCP 示例
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
// 服务端
fn tcp_server() -> std::io::Result<()> {
let listener = TcpListener::bind("127.0.0.1:8080")?;
for stream in listener.incoming() {
let mut stream = stream?;
let mut buffer = [0; 1024];
stream.read(&mut buffer)?;
stream.write_all(b"Received")?;
}
Ok(())
}
// 客户端
fn tcp_client() -> std::io::Result<()> {
let mut stream = TcpStream::connect("127.0.0.1:8080")?;
stream.write_all(b"Hello")?;
let mut response = [0; 8];
stream.read_exact(&mut response)?;
println!("Server response: {:?}", response);
Ok(())
}
3、异步 TCP 示例(使用 Tokio)
# Cargo.toml 依赖
[dependencies]
tokio = { version = "1.0", features = ["full"] }
use tokio::net::{TcpListener, TcpStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
// 异步服务端
async fn async_tcp_server() -> tokio::io::Result<()> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buf = [0; 1024];
socket.read(&mut buf).await?;
socket.write_all(b"Async Response").await
});
}
}
// 异步客户端
async fn async_tcp_client() -> tokio::io::Result<()> {
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.write_all(b"Async Hello").await?;
let mut response = [0; 14];
stream.read_exact(&mut response).await?;
println!("Async response: {:?}", response);
Ok(())
}
4、UDP 通信示例
use std::net::UdpSocket;
fn udp_example() -> std::io::Result<()> {
// 服务端
let server_socket = UdpSocket::bind("127.0.0.1:8081")?;
let mut buf = [0; 1024];
let (_, client_addr) = server_socket.recv_from(&mut buf)?;
server_socket.send_to(b"UDP ACK", client_addr)?;
// 客户端
let client_socket = UdpSocket::bind("127.0.0.1:0")?;
client_socket.send_to(b"UDP Data", "127.0.0.1:8081")?;
let mut ack = [0; 7];
client_socket.recv_from(&mut ack)?;
println!("UDP ACK: {:?}", ack);
Ok(())
}
5、高级主题
- 协议设计:
- 使用
serde
序列化数据(JSON/Protobuf)。 - 实现自定义二进制协议(如
byteorder
库)。
- 使用
- 性能优化:
- 零拷贝技术(
bytes::Bytes
)。 - 连接池管理(
bb8
库)。
- 零拷贝技术(
- 安全实践:
- TLS 加密(
rustls
库)。 - 防 DoS 攻击(速率限制/超时控制)。
- TLS 加密(