curl –proto ‘=https’ –tlsv1.2 -sSf https://sh.rustup.rs | sh
. “$HOME/.cargo/env”
curl –proto ‘=https’ –tlsv1.2 -sSf https://sh.rustup.rs | sh
. “$HOME/.cargo/env”
第一步 安装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());
}
}
}
服务端代码:socket阻塞循环读
use std::io::{Read, Write};
use std::net::{TcpListener,TcpStream};
use std::thread;
fn handle_client(mut stream: TcpStream) {
let mut buffer = [0; 1024];
loop {
match stream.read(&mut buffer) {
Ok(0) => {
// 客户端关闭连接
println!("Client disconnected");
break;
}
Ok(size) => {
// 读取到数据,回显给客户端
let data = &buffer[..size];
let received = String::from_utf8_lossy(data);
println!("Received data: {}", received);
// 检查是否是telnet的断开命令(IAC IP)
if size >= 3 && buffer[0] == 255 && buffer[1] == 244 {
println!("Detected telnet disconnect command (IAC IP)");
if let Err(e) = stream.shutdown(std::net::Shutdown::Both) {
println!("Error shutting down stream: {}", e);
}
break;
}
// 检查普通ASCII的CTRL+C (3)
if buffer[..size].contains(&3) {
println!("Detected CTRL+C, closing connection");
if let Err(e) = stream.shutdown(std::net::Shutdown::Both) {
println!("Error shutting down stream: {}", e);
}
break;
}
if let Err(e) = stream.write_all(&buffer[..size]) {
println!("Error writing to stream: {}", e);
break;
}
}
Err(e) => {
// 发生错误,关闭连接
println!("Error: {}", e);
break;
}
}
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:65432").unwrap();
println!("Server listening on 127.0.0.1:65432");
for stream in listener.incoming() {
match stream {
Ok(stream) => {
// 为每个客户端连接创建一个新线程
thread::spawn(move || {
handle_client(stream);
});
}
Err(e) => {
println!("Error accepting stream: {}", e);
break;
}
}
}
// 注意:在实际应用中,应该优雅地关闭监听器,比如监听一个关闭信号。
// 这里为了简化,直接退出主循环后程序将结束。
}
client 端代码
use std::io::{self, Read, Write};
use std::net::TcpStream;
fn main() -> io::Result<()> {
let mut stream = TcpStream::connect("127.0.0.1:65432")?;
println!("Connected to server!");
loop {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
if input.contains('\x03') { // CTRL+C
println!("Sending CTRL+C to server");
stream.write_all(input.as_bytes())?;
break;
}
stream.write_all(input.as_bytes())?;
let mut buffer = [0; 1024];
let size = stream.read(&mut buffer)?;
if size == 0 {
println!("Server closed connection");
break;
}
println!("Server echo: {}", String::from_utf8_lossy(&buffer[..size]));
}
Ok(())
}
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::Path;
fn main() -> std::io::Result<()> {
let file_path = Path::new("hello.txt");
let mut file = OpenOptions::new()
.create(true)
.append(true)
.open(file_path)?;
file.write_all(b"Hello, World!\n")?;
println!("成功追加内容到文件: {}", file_path.display());
Ok(())
}
创建文件并且写入
fn read() -> Result<(), Box<dyn Error>> {
let file_path = Path::new("hello.txt");
match File::open(file_path) {
Ok(mut file) => {
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("文件内容:\n{}", contents);
}
Err(e) => eprintln!("无法打开文件: {}", e),
}
Ok(())
}
读取文件
基本命令
cargo new --bin helloworld
创建helloworld 项目项目为bin 可执行文件
cargo run
编译项目并且执行可执行文件
cargo build
编译项目