Appearance
Rust 异步编程
异步编程是 Rust 中处理并发的一种方式,它允许我们在等待 I/O 操作时执行其他任务。本章节将介绍 Rust 中的异步编程。
异步编程基础
异步函数
使用 async 关键字定义异步函数:
rust
async fn hello() {
println!("Hello, async world!");
}
fn main() {
let future = hello();
// 执行 future
tokio::runtime::Runtime::new().unwrap().block_on(future);
}Future
异步函数返回一个 Future,它表示一个异步操作:
rust
use std::future::Future;
async fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let future: impl Future<Output = i32> = add(5, 3);
let result = tokio::runtime::Runtime::new().unwrap().block_on(future);
println!("Result: {}", result);
}异步运行时
Tokio
Tokio 是 Rust 中最流行的异步运行时:
rust
use tokio::time::{sleep, Duration};
async fn say_hello() {
println!("Hello");
sleep(Duration::from_secs(1)).await;
println!("World");
}
#[tokio::main]
async fn main() {
say_hello().await;
}async-std
async-std 是另一个流行的异步运行时:
rust
use async_std::task::sleep;
use std::time::Duration;
async fn say_hello() {
println!("Hello");
sleep(Duration::from_secs(1)).await;
println!("World");
}
#[async_std::main]
async fn main() {
say_hello().await;
}await 关键字
使用 await 关键字等待异步操作完成:
rust
use tokio::time::{sleep, Duration};
async fn task1() {
println!("Task 1 started");
sleep(Duration::from_secs(1)).await;
println!("Task 1 completed");
}
async fn task2() {
println!("Task 2 started");
sleep(Duration::from_secs(2)).await;
println!("Task 2 completed");
}
#[tokio::main]
async fn main() {
// 串行执行
task1().await;
task2().await;
// 并行执行
let t1 = tokio::spawn(task1());
let t2 = tokio::spawn(task2());
t1.await.unwrap();
t2.await.unwrap();
}异步 I/O
异步文件操作
rust
use tokio::fs::File;
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> io::Result<()> {
// 写入文件
let mut file = File::create("hello.txt").await?;
file.write_all(b"Hello, async I/O!").await?;
// 读取文件
let mut file = File::open("hello.txt").await?;
let mut contents = String::new();
file.read_to_string(&mut contents).await?;
println!("File contents: {}", contents);
Ok(())
}异步网络操作
rust
use tokio::net::TcpListener;
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> io::Result<()> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
println!("Server listening on 127.0.0.1:8080");
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buffer = [0; 1024];
// 读取数据
let n = socket.read(&mut buffer).await.unwrap();
println!("Received: {}", String::from_utf8_lossy(&buffer[..n]));
// 发送数据
socket.write_all(b"Hello from server!").await.unwrap();
});
}
}异步流
Stream
Stream 是异步的迭代器:
rust
use tokio::stream::StreamExt;
use tokio::time::{interval, Duration};
#[tokio::main]
async fn main() {
let mut interval = interval(Duration::from_millis(100));
let mut count = 0;
while let Some(_) = interval.next().await {
println!("Tick {}", count);
count += 1;
if count >= 5 {
break;
}
}
}错误处理
Result 和 async
rust
use tokio::fs::File;
use tokio::io::{self, AsyncReadExt};
async fn read_file() -> Result<String, io::Error> {
let mut file = File::open("hello.txt").await?;
let mut contents = String::new();
file.read_to_string(&mut contents).await?;
Ok(contents)
}
#[tokio::main]
async fn main() {
match read_file().await {
Ok(contents) => println!("File contents: {}", contents),
Err(e) => println!("Error: {}", e),
}
}总结
- 异步函数:使用
async关键字定义 - Future:表示一个异步操作
- 异步运行时:Tokio 和 async-std
- await:等待异步操作完成
- 异步 I/O:文件和网络操作
- Stream:异步迭代器
- 错误处理:与同步代码类似
异步编程是 Rust 中处理并发的强大工具,它允许我们在等待 I/O 操作时执行其他任务,从而提高程序的效率。通过本章节的学习,你应该已经掌握了 Rust 中异步编程的基本概念和使用方法。