- 引入依赖:
在
Cargo.toml
文件中添加 tokio
及其相关依赖,例如:
[dependencies]
tokio = { version = "1", features = ["full"] }
- 编写异步TCP服务器代码:
use std::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
// 处理单个连接的异步函数
async fn handle_connection(mut socket: tokio::net::TcpStream) {
let mut buffer = [0; 1024];
loop {
let n = match socket.read(&mut buffer).await {
Ok(n) if n == 0 => break,
Ok(n) => n,
Err(e) => {
eprintln!("read error: {}", e);
break;
}
};
if let Err(e) = socket.write_all(&buffer[..n]).await {
eprintln!("write error: {}", e);
break;
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080")?;
loop {
let (socket, _) = listener.accept().await?;
// 使用tokio的spawn处理并发连接
tokio::spawn(handle_connection(socket));
}
}
解释
- 引入依赖:
tokio
是Rust中常用的异步运行时,features = ["full"]
表示引入完整功能集,包括网络等功能。
handle_connection
函数:
- 这个异步函数负责处理单个TCP连接。它使用
AsyncReadExt
和 AsyncWriteExt
特征来异步读写数据。
- 在
loop
中,尝试从 socket
读取数据到 buffer
中。如果读取到的数据长度为0,表示连接关闭,退出循环。如果读取或写入过程中出现错误,也退出循环并打印错误信息。
main
函数:
- 使用
TcpListener::bind
绑定到指定地址和端口(这里是 127.0.0.1:8080
)。
- 在
loop
中,通过 listener.accept().await
等待新的连接。一旦有新连接,使用 tokio::spawn
创建一个新的任务来处理这个连接,这样就实现了并发处理连接。
#[tokio::main]
宏将普通的 main
函数转换为异步函数,并在Tokio运行时中执行。