第一步 安装tokio库
cargo add tokio --features full
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// 绑定到本地地址的8080端口
let listener = TcpListener::bind("127.0.0.1:8080").await?;
println!("服务器正在监听 127.0.0.1:8080");
loop {
// 等待新的连接
let (socket, addr) = listener.accept().await?;
println!("接收到来自 {} 的新连接", addr);
// 为每个连接生成一个新任务
tokio::spawn(async move {
if let Err(e) = handle_connection(socket).await {
println!("处理连接时出错: {}", e);
}
});
}
}
async fn handle_connection(mut socket: TcpStream) -> Result<(), Box<dyn Error>> {
// 创建一个缓冲区来存储数据
let mut buf = [0; 1024];
loop {
// 读取数据
let size = match socket.read(&mut buf).await {
// 客户端关闭了连接
Ok(size) if size == 0 => return Ok(()),
Ok(size) => size,
Err(e) => {
return Err(e.into());
}
};
let data = &buf[..size];
let received = String::from_utf8_lossy(data);
println!("Received data: {}", received);
// 检查是否是telnet的断开命令(IAC IP)
if size >= 3 && buf[0] == 255 && buf[1] == 244 {
println!("Detected telnet disconnect command (IAC IP)");
//显示关闭连接并且传播异常
socket.shutdown().await?;
//这个也能退出事件循环 关闭连接
return Ok(());
}
// 检查普通ASCII的CTRL+C (3)
if buf[..size].contains(&3) {
println!("Detected CTRL+C, closing connection");
//显示关闭连接并且传播异常
socket.shutdown().await?;
//这个也能退出事件循环 关闭连接
return Ok(());
}
println!("接收到 {} 字节数据", size);
// 将数据写回客户端
if let Err(e) = socket.write_all(&buf[0..size]).await {
return Err(e.into());
}
}
}