使用 Tokio 构建异步应用
使用 Tokio 运行时高效执行异步任务,处理 I/O 和其他并发操作。
使用 Tokio 构建异步应用 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。
认识 Tokio 运行时
欢迎回来!在上一课中,您学习了async和await。但是,async函数究竟是如何运行的呢?
这正是 Tokio 这样的异步运行时发挥作用的地方。Tokio 是一个功能强大的库,为您的异步 Rust 代码提供执行环境。
- 它会调度并执行
Future。 - 处理非阻塞 I/O 操作。
- 高效地管理并发任务。
运行您的异步代码
要开始使用 Tokio,通常需要使用#[tokio::main]属性宏。这个宏会将您的async fn main()转换为标准的fn main(),后者会初始化 Tokio 运行时并运行您的异步代码。
您可以把它看作异步应用的入口点。
use tokio;
#[tokio::main]
async fn main() {
println!("Hello from Tokio!");
}生成新的异步任务
Tokio 的核心功能之一,是能够并发运行多个异步操作。您可以使用tokio::spawn来实现这一点。
tokio::spawn接收一个Future,并将其调度到 Tokio 运行时上运行。这样,主任务可以继续执行,同时生成的任务会在后台运行。
- 它不会阻塞。
- 它会返回一个
JoinHandle,用于等待任务完成。 - 各个任务彼此独立地运行。
<code>tokio::spawn</code>实战
让我们看看tokio::spawn如何让您并发执行代码。请注意,两条消息都会出现,但由于休眠操作,"done"消息可能会先于"task complete"消息打印出来。
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
// Spawn a new task
let handle = tokio::spawn(async {
sleep(Duration::from_secs(1)).await;
println!("Async task complete!");
});
println!("Main task continuing...");
// Wait for the spawned task to finish
handle.await.unwrap();
println!("All tasks done.");
}等待多个任务
当您有多个任务时,通常需要等待它们全部完成。Tokio 提供了tokio::join!宏来实现这一目的。
tokio::join!允许您并发等待多个 future,并组合它们的结果。它类似于等待多个JoinHandle,但对于固定的一组 future,通常写法更简洁。
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let task1 = async {
sleep(Duration::from_secs(1)).await;
println!("Task 1 finished");
1
};
let task2 = async {
sleep(Duration::from_millis(500)).await;
println!("Task 2 finished");
2
};
let (result1, result2) = tokio::join!(task1, task2);
println!("Results: {}, {}", result1, result2);
}使用 Tokio 进行异步文件 I/O
传统的文件操作可能会阻塞线程,这对异步应用来说是不利的。Tokio 的tokio::fs模块提供了文件系统操作的异步版本。
这样一来,即使读取大型文件或执行许多文件操作,您的应用也能保持响应,因为 I/O 会以非阻塞方式处理。
tokio::fs::read_to_stringtokio::fs::write- 需要更多控制时使用
tokio::fs::File
异步读取文件
下面介绍如何使用tokio::fs::read_to_string异步读取文件。要运行这段代码,请确保 Rust 项目的同一目录中有一个名为hello.txt的文件(例如位于src/目录中或项目根目录下),并且文件中包含一些内容。
use tokio::fs;
#[tokio::main]
async fn main() {
let path = "hello.txt";
// Create a dummy file for the example if it doesn't exist
// In a real app, you'd handle file creation/existence more robustly
if let Err(_) = fs::metadata(path).await {
fs::write(path, "Hello, Tokio file!").await.unwrap();
}
match fs::read_to_string(path).await {
Ok(content) => println!("File content: '{}'", content),
Err(e) => eprintln!("Error reading file: {}", e),
}
}异步网络操作
Tokio 在网络编程中真正展现了实力。它的tokio::net模块为 TCP 和 UDP 通信提供了非阻塞基础功能。
这对于构建高性能服务器或客户端至关重要,因为它们可以同时处理许多连接,而不必为每个连接创建单独的线程。
- 服务器使用
tokio::net::TcpListener。 - 客户端连接使用
tokio::net::TcpStream。
异步 TCP 服务器的基本结构
虽然完整的服务器较为复杂,但这段代码展示了使用 Tokio 构建的异步 TCP 服务器的核心循环。它会监听传入的连接,并为每个连接打印一条消息。请尝试运行它,然后在浏览器中打开http://127.0.0.1:8080来查看连接。
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
println!("Listening on: {}", listener.local_addr().unwrap());
loop {
let (socket, addr) = listener.accept().await.unwrap();
println!("Accepted connection from: {}", addr);
// In a real server, you'd spawn a task to handle the socket
// tokio::spawn(async move { handle_connection(socket).await; });
}
}
// fn handle_connection(socket: TcpStream) { /* ... */ } // PlaceholderTokio 任务挑战
请思考下面这段使用 Tokio 的 Rust 代码。程序运行时,控制台打印的第一条消息会是什么?
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
tokio::spawn(async {
sleep(Duration::from_millis(200)).await;
println!("Task 1: Done");
});
tokio::spawn(async {
sleep(Duration::from_millis(100)).await;
println!("Task 2: Done");
});
println!("Main: Starting tasks...");
sleep(Duration::from_millis(300)).await;
println!("Main: Finishing.");
}回顾:使用 Tokio 构建应用
您已经在使用 Rust 和 Tokio 构建异步应用方面迈出了重要一步!
- Tokio 充当异步运行时,执行您的
async代码。 #[tokio::main]是程序的异步入口点。tokio::spawn让您能够并发运行多个任务。tokio::join!帮助您等待多个 future。- Tokio 为文件(
tokio::fs)和网络(tokio::net)提供非阻塞 I/O。
这些工具是使用 Rust 创建高并发、响应迅速的应用的基础。请继续练习!
用 AI 导师学习 Rust — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 39
- 课程
- 144
常见问题解答
「使用 Tokio 构建异步应用」课时是免费的吗?
是的 — 「使用 Tokio 构建异步应用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。
「使用 Tokio 构建异步应用」这节课中我会学到什么?
使用 Tokio 运行时高效执行异步任务,处理 I/O 和其他并发操作。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 3 节。
「使用 Tokio 构建异步应用」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 异步编程与 Async/Await 入门
- 使用 Tokio 构建异步应用
- 使用 Future 与任务