跳到主要内容

常用标准库模块

Rust 标准库提供了丰富的功能模块,涵盖了文件操作、路径处理、环境变量、进程管理、时间处理和网络编程等常见任务。本章将介绍这些常用模块的核心功能和使用方法。

文件系统操作(std::fs)

std::fs 模块提供了跨平台的文件系统操作功能。所有方法都设计为在不同操作系统上工作一致,平台特定的功能可以在 std::os 模块中找到。

文件读写

读取文件

use std::fs;
use std::io;

fn main() -> io::Result<()> {
// 方式一:一次性读取整个文件到字符串
let content = fs::read_to_string("hello.txt")?;
println!("文件内容:\n{}", content);

// 方式二:读取为字节数组
let bytes = fs::read("binary.dat")?;
println!("读取了 {} 字节", bytes.len());

// 方式三:使用 File 进行更精细的控制
use std::fs::File;
use std::io::Read;

let mut file = File::open("hello.txt")?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
println!("内容: {}", buffer);

Ok(())
}

三种方式的区别

方法适用场景内存使用
read_to_string小型文本文件一次性加载全部内容
read二进制文件或文本返回 Vec<u8>
File::open + Read大文件、需要流式处理可控制缓冲区大小

写入文件

use std::fs;
use std::io;

fn main() -> io::Result<()> {
// 方式一:一次性写入(覆盖已存在的文件)
fs::write("output.txt", "Hello, Rust!")?;

// 方式二:使用 File 进行更精细的控制
use std::fs::File;
use std::io::Write;

let mut file = File::create("output.txt")?; // 创建或覆盖
file.write_all(b"Hello, Rust!")?;

// 方式三:追加写入
use std::fs::OpenOptions;

let mut file = OpenOptions::new()
.write(true)
.append(true)
.open("output.txt")?;
writeln!(file, "\n追加的一行")?;

Ok(())
}

OpenOptions 详细配置

OpenOptions 提供了打开文件的各种选项:

use std::fs::OpenOptions;
use std::io;

fn main() -> io::Result<()> {
// 读写模式,文件不存在则创建
let file = OpenOptions::new()
.read(true) // 可读
.write(true) // 可写
.create(true) // 不存在则创建
.open("config.txt")?;

// 只写模式,追加内容
let file = OpenOptions::new()
.append(true)
.open("log.txt")?;

// 创建新文件,如果已存在则失败
let file = OpenOptions::new()
.write(true)
.create_new(true) // 文件必须不存在
.open("new_file.txt");

// 根据结果处理
match file {
Ok(f) => println!("文件创建成功"),
Err(e) => println!("文件已存在或其他错误: {}", e),
}

Ok(())
}

目录操作

use std::fs;
use std::io;
use std::path::Path;

fn main() -> io::Result<()> {
// 创建目录
fs::create_dir("my_dir")?;

// 递归创建目录(类似 mkdir -p)
fs::create_dir_all("a/b/c/d")?;

// 删除空目录
fs::remove_dir("my_dir")?;

// 递归删除目录及其内容(危险操作,谨慎使用)
// fs::remove_dir_all("a")?;

// 读取目录内容
for entry in fs::read_dir(".")? {
let entry = entry?;
let path = entry.path();

// 获取文件名
if let Some(name) = path.file_name() {
println!("名称: {}", name.to_string_lossy());
}

// 获取文件类型
let file_type = entry.file_type()?;
if file_type.is_dir() {
println!(" [目录]");
} else if file_type.is_file() {
println!(" [文件]");
} else if file_type.is_symlink() {
println!(" [符号链接]");
}
}

Ok(())
}

文件元数据

use std::fs;
use std::io;

fn main() -> io::Result<()> {
let metadata = fs::metadata("hello.txt")?;

// 文件大小
println!("大小: {} 字节", metadata.len());

// 是否为目录
println!("是目录: {}", metadata.is_dir());

// 是否为文件
println!("是文件: {}", metadata.is_file());

// 是否为符号链接
println!("是符号链接: {}", metadata.is_symlink());

// 权限
let permissions = metadata.permissions();
println!("只读: {}", permissions.readonly());

// 修改时间
if let Ok(modified) = metadata.modified() {
println!("修改时间: {:?}", modified);
}

// 检查文件是否存在
let exists = fs::exists("hello.txt")?;
println!("文件存在: {}", exists);

Ok(())
}

文件操作

use std::fs;
use std::io;

fn main() -> io::Result<()> {
// 复制文件
let bytes_copied = fs::copy("source.txt", "dest.txt")?;
println!("复制了 {} 字节", bytes_copied);

// 重命名/移动文件
fs::rename("old_name.txt", "new_name.txt")?;

// 删除文件
fs::remove_file("unwanted.txt")?;

// 获取规范路径(解析符号链接和相对路径)
let canonical = fs::canonicalize("../some/path")?;
println!("规范路径: {}", canonical.display());

// 创建硬链接
fs::hard_link("original.txt", "link.txt")?;

Ok(())
}

TOCTOU 竞态条件

文件系统操作存在一种称为 TOCTOU(Time of Check to Time of Use)的竞态条件。这发生在程序检查条件(如文件是否存在)然后使用检查结果做决策时,条件可能在检查和使用之间发生了变化。

use std::fs::File;
use std::io;

// 错误示例:存在 TOCTOU 问题
fn bad_create_file(path: &str) -> io::Result<()> {
// 检查文件是否存在
if !std::path::Path::new(path).exists() {
// 在检查和创建之间,其他进程可能已创建该文件!
File::create(path)?;
}
Ok(())
}

// 正确做法:使用原子操作
fn good_create_file(path: &str) -> io::Result<()> {
use std::fs::OpenOptions;

// create_new 是原子操作,只有在文件不存在时才创建
OpenOptions::new()
.write(true)
.create_new(true)
.open(path)?;

Ok(())
}

fn main() -> io::Result<()> {
good_create_file("test.txt")?;
Ok(())
}

路径处理(std::path)

std::path 模块提供了跨平台的路径操作功能。它包含两个主要类型:

  • Path:路径切片,类似 str,是不可变的借用类型
  • PathBuf:可增长的路径,类似 String,拥有所有权

Path 和 PathBuf 的关系

use std::path::{Path, PathBuf};

fn main() {
// Path 从字符串切片创建
let path = Path::new("/home/user/documents/file.txt");

// PathBuf 可以修改
let mut path_buf = PathBuf::new();
path_buf.push("/home");
path_buf.push("user");
path_buf.push("documents");

// 从 PathBuf 获取 Path 的引用
let path_ref: &Path = &path_buf;

// PathBuf 从 Path 创建
let owned: PathBuf = path.to_path_buf();

// 从字符串创建 PathBuf
let from_str = PathBuf::from("/usr/local/bin");

println!("路径: {}", path.display());
println!("PathBuf: {}", path_buf.display());
}

路径解析

use std::path::Path;

fn main() {
let path = Path::new("/home/user/documents/file.txt");

// 获取各部分
println!("父目录: {:?}", path.parent()); // Some("/home/user/documents")
println!("文件名: {:?}", path.file_name()); // Some("file.txt")
println!("扩展名: {:?}", path.extension()); // Some("txt")
println!("文件主名: {:?}", path.file_stem()); // Some("file")

// 检查路径
println!("是绝对路径: {}", path.is_absolute()); // true
println!("是相对路径: {}", path.is_relative()); // false

// 检查是否有特定前缀
let win_path = Path::new(r"C:\Windows\System32");
println!("有根前缀: {}", win_path.has_root());

// 获取路径组件
println!("\n路径组件:");
for component in path.components() {
println!(" {:?}", component);
}

// 相对路径处理
let rel = Path::new("projects/my_app/src/main.rs");
println!("\n相对路径的父目录: {:?}", rel.parent());
}

路径构建

use std::path::PathBuf;

fn main() {
// 使用 push 构建路径
let mut path = PathBuf::new();
path.push("/home");
path.push("user");
path.push("documents");
println!("构建的路径: {}", path.display());

// 使用 join 方法(更简洁)
let path = PathBuf::from("/home/user")
.join("documents")
.join("file.txt");
println!("使用 join: {}", path.display());

// 设置扩展名
let mut path = PathBuf::from("file");
path.set_extension("txt");
println!("设置扩展名后: {}", path.display()); // file.txt

// 替换扩展名
let mut path = PathBuf::from("document.txt");
path.set_extension("pdf");
println!("替换扩展名后: {}", path.display()); // document.pdf

// 使用 with_extension 创建新路径
let path = Path::new("image.png");
let new_path = path.with_extension("jpg");
println!("原路径: {}, 新路径: {}", path.display(), new_path.display());

// 使用 with_file_name 替换文件名
let path = Path::new("/home/user/old.txt");
let new_path = path.with_file_name("new.txt");
println!("替换文件名: {}", new_path.display());

// 从迭代器收集
let path: PathBuf = ["home", "user", "documents"].iter().collect();
println!("从迭代器: {}", path.display());
}

路径比较和匹配

use std::path::Path;

fn main() {
let path = Path::new("/home/user/documents/file.txt");

// 检查前缀和后缀
println!("以 /home 开头: {}", path.starts_with("/home"));
println!("以 file.txt 结尾: {}", path.ends_with("file.txt"));

// 注意:starts_with 和 ends_with 是基于路径组件的
println!("以 user/documents 结尾: {}", path.ends_with("user/documents"));
println!("以 ocuments 结尾: {}", path.ends_with("ocuments")); // false!

// 路径相等比较
let other = Path::new("/home/user/documents/file.txt");
println!("路径相等: {}", path == other);

// strip_prefix 去除前缀
if let Ok(relative) = path.strip_prefix("/home/user") {
println!("相对路径: {}", relative.display()); // documents/file.txt
}

// 路径连接
let base = Path::new("/home/user");
let full = base.join("documents/file.txt");
println!("连接后: {}", full.display());
}

实际应用示例

use std::path::{Path, PathBuf};
use std::fs;

// 安全地构建配置文件路径
fn get_config_path(app_name: &str, config_file: &str) -> PathBuf {
// 在 Unix 系统上,配置通常在 ~/.config/app_name/
// 在 Windows 上,通常在 %APPDATA%\app_name\

#[cfg(unix)]
{
let mut path = PathBuf::from(std::env::var("HOME").unwrap_or_else(|_| ".".to_string()));
path.push(".config");
path.push(app_name);
path.push(config_file);
path
}

#[cfg(windows)]
{
let mut path = PathBuf::from(std::env::var("APPDATA").unwrap_or_else(|_| ".".to_string()));
path.push(app_name);
path.push(config_file);
path
}
}

// 遍历目录并筛选特定扩展名
fn find_files_with_extension(dir: &Path, ext: &str) -> Vec<PathBuf> {
let mut results = Vec::new();

if let Ok(entries) = fs::read_dir(dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
// 递归搜索子目录
results.extend(find_files_with_extension(&path, ext));
} else if path.extension().map_or(false, |e| e == ext) {
results.push(path);
}
}
}

results
}

fn main() {
// 获取配置路径
let config_path = get_config_path("myapp", "config.toml");
println!("配置文件路径: {}", config_path.display());

// 查找所有 Rust 文件
if let Ok(current_dir) = std::env::current_dir() {
let rust_files = find_files_with_extension(&current_dir, "rs");
println!("找到 {} 个 Rust 文件", rust_files.len());
for file in rust_files.iter().take(5) {
println!(" {}", file.display());
}
}
}

环境变量(std::env)

std::env 模块提供了检查和操作进程环境的功能,包括环境变量、命令行参数、当前目录等。

环境变量操作

use std::env;
use std::io;

fn main() -> io::Result<()> {
// 读取环境变量
match env::var("HOME") {
Ok(value) => println!("HOME: {}", value),
Err(e) => println!("无法获取 HOME: {}", e),
}

// 使用 var_os 获取 OsString(可能包含非 UTF-8 数据)
if let Some(path) = env::var_os("PATH") {
println!("PATH: {:?}", path);
}

// 设置环境变量(注意:Rust 2024 中这是 unsafe 操作)
// unsafe {
// env::set_var("MY_VAR", "my_value");
// }

// 删除环境变量(注意:Rust 2024 中这是 unsafe 操作)
// unsafe {
// env::remove_var("MY_VAR");
// }

// 遍历所有环境变量
println!("\n所有环境变量:");
for (key, value) in env::vars() {
println!("{} = {}", key, value);
break; // 只显示第一个
}

Ok(())
}
Rust 2024 Edition 变更

从 Rust 2024 Edition 开始,std::env::set_varstd::env::remove_var 函数被标记为 unsafe。这是因为不当使用这些函数可能导致线程安全问题和其他难以追踪的 bug。

替代方案

// 如果需要在子进程中设置环境变量,使用 Command 的 env 方法
use std::process::Command;

let output = Command::new("my-program")
.env("MY_VAR", "value")
.output()?;

如果你确定需要修改当前进程的环境变量:

// Rust 2024: 需要 unsafe 块
unsafe {
std::env::set_var("MY_VAR", "value");
}

命令行参数

use std::env;

fn main() {
// 获取所有参数
let args: Vec<String> = env::args().collect();

// args[0] 是程序名称
println!("程序名: {}", args[0]);

// 处理命令行参数
for (i, arg) in args.iter().enumerate().skip(1) {
println!("参数 {}: {}", i, arg);
}

// 简单的参数解析
let mut verbose = false;
let mut input_file = String::new();

let mut iter = env::args().skip(1);
while let Some(arg) = iter.next() {
match arg.as_str() {
"-v" | "--verbose" => verbose = true,
"-f" | "--file" => {
input_file = iter.next().expect("需要指定文件名");
}
"-h" | "--help" => {
println!("用法: program [-v] [-f file]");
return;
}
_ => println!("未知参数: {}", arg),
}
}

println!("详细模式: {}", verbose);
println!("输入文件: {}", input_file);
}

当前目录和程序信息

use std::env;

fn main() {
// 获取当前工作目录
match env::current_dir() {
Ok(dir) => println!("当前目录: {}", dir.display()),
Err(e) => println!("无法获取当前目录: {}", e),
}

// 获取当前可执行文件路径
match env::current_exe() {
Ok(path) => println!("可执行文件: {}", path.display()),
Err(e) => println!("无法获取可执行文件路径: {}", e),
}

// 设置当前目录
// if let Err(e) = env::set_current_dir("/tmp") {
// println!("无法切换目录: {}", e);
// }

// 获取用户主目录
#[cfg(unix)]
{
if let Some(home) = env::var_os("HOME") {
println!("用户主目录: {:?}", home);
}
}

#[cfg(windows)]
{
if let Some(profile) = env::var_os("USERPROFILE") {
println!("用户目录: {:?}", profile);
}
}
}

进程管理(std::process)

std::process 模块用于创建和管理子进程,以及控制当前进程。

运行命令

use std::process::Command;
use std::io;

fn main() -> io::Result<()> {
// 基本命令执行
let output = Command::new("ls")
.arg("-l")
.output()?; // 等待命令完成并收集输出

println!("状态: {}", output.status);
println!("标准输出:\n{}", String::from_utf8_lossy(&output.stdout));
println!("标准错误:\n{}", String::from_utf8_lossy(&output.stderr));

Ok(())
}

更灵活的命令控制

use std::process::{Command, Stdio};
use std::io::{self, Write};

fn main() -> io::Result<()> {
// 捕获输出
let output = Command::new("echo")
.arg("hello world")
.output()?;
println!("输出: {}", String::from_utf8_lossy(&output.stdout));

// 忽略输出
Command::new("echo")
.arg("ignored")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()?;

// 管道:将一个命令的输出传递给另一个命令
let mut first = Command::new("echo")
.arg("hello from pipe")
.stdout(Stdio::piped())
.spawn()?;

let second = Command::new("grep")
.arg("hello")
.stdin(first.stdout.take().unwrap())
.output()?;

println!("管道输出: {}", String::from_utf8_lossy(&second.stdout));

// 向进程输入数据
let mut child = Command::new("cat")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;

// 写入输入
{
let stdin = child.stdin.as_mut().expect("无法获取 stdin");
stdin.write_all(b"Hello from Rust\n")?;
}

// 读取输出
let output = child.wait_with_output()?;
println!("cat 输出: {}", String::from_utf8_lossy(&output.stdout));

Ok(())
}

进程控制和状态

use std::process::Command;
use std::io;

fn main() -> io::Result<()> {
// 启动进程但不等待
let mut child = Command::new("sleep")
.arg("5")
.spawn()?;

println!("子进程 ID: {}", child.id());

// 检查是否完成(非阻塞)
match child.try_wait() {
Ok(Some(status)) => println!("进程已完成: {}", status),
Ok(None) => {
println!("进程还在运行,等待中...");
// 等待进程完成
let status = child.wait()?;
println!("进程结束: {}", status);
}
Err(e) => println!("错误: {}", e),
}

// 获取退出码
let output = Command::new("ls")
.arg("/nonexistent")
.output()?;

if !output.status.success() {
println!("命令失败,退出码: {:?}", output.status.code());
}

Ok(())
}

设置环境变量和工作目录

use std::process::Command;
use std::io;

fn main() -> io::Result<()> {
let output = Command::new("printenv")
.env("MY_VAR", "hello") // 设置环境变量
.env("ANOTHER_VAR", "world")
.env_remove("PATH") // 移除环境变量
.current_dir("/tmp") // 设置工作目录
.output()?;

println!("输出: {}", String::from_utf8_lossy(&output.stdout));

Ok(())
}

终止程序

use std::process;

fn main() {
let args: Vec<String> = std::env::args().collect();

if args.len() < 2 {
eprintln!("用法: {} <参数>", args[0]);
process::exit(1); // 立即退出,返回退出码
}

// 正常退出
process::exit(0);
}

exit vs abort 的区别

use std::process;

fn example() {
// exit:正常退出,会执行析构函数
process::exit(0);

// abort:立即终止,不执行析构函数
// 用于无法恢复的错误情况
// process::abort();
}

时间处理(std::time)

std::time 模块提供了时间测量和持续时间处理的功能。

Duration 类型

Duration 表示时间跨度,是 std::time 的核心类型:

use std::time::Duration;

fn main() {
// 创建 Duration
let five_seconds = Duration::from_secs(5);
let hundred_millis = Duration::from_millis(100);
let one_micro = Duration::from_micros(1);
let one_nano = Duration::from_nanos(1);

// 使用 new
let custom = Duration::new(5, 500_000_000); // 5秒 + 500毫秒
println!("自定义时长: {:?}", custom);

// 获取各部分
println!("秒: {}", custom.as_secs());
println!("毫秒: {}", custom.as_millis());
println!("微秒: {}", custom.as_micros());
println!("纳秒: {}", custom.as_nanos());
println!("子纳秒部分: {}", custom.subsec_nanos());

// 运算
let sum = five_seconds + hundred_millis;
let diff = five_seconds - hundred_millis;
let doubled = five_seconds * 2;
let halved = five_seconds / 2;

println!("相加: {:?}", sum);
println!("相减: {:?}", diff);
println!("翻倍: {:?}", doubled);
println!("减半: {:?}", halved);

// 比较
println!("five_seconds > hundred_millis: {}", five_seconds > hundred_millis);
}

测量执行时间

use std::time::Instant;

fn main() {
let start = Instant::now();

// 执行一些操作
let mut sum = 0;
for i in 0..1_000_000 {
sum += i;
}

let duration = start.elapsed();
println!("执行耗时: {:?}", duration);
println!("执行耗时: {} 纳秒", duration.as_nanos());
println!("执行耗时: {} 毫秒", duration.as_millis());

// 检查是否超时
let deadline = Instant::now() + std::time::Duration::from_secs(5);

// 检查是否已经过了某个时间点
if Instant::now() < deadline {
println!("还有时间");
}

// 计算剩余时间
let remaining = deadline.saturating_duration_since(Instant::now());
println!("剩余时间: {:?}", remaining);
}

简单计时器

use std::time::{Duration, Instant};

struct Timer {
start: Instant,
name: String,
}

impl Timer {
fn new(name: &str) -> Self {
Timer {
start: Instant::now(),
name: name.to_string(),
}
}

fn elapsed(&self) -> Duration {
self.start.elapsed()
}

fn reset(&mut self) {
self.start = Instant::now();
}
}

impl Drop for Timer {
fn drop(&mut self) {
println!("[{}] 耗时: {:?}", self.name, self.elapsed());
}
}

fn main() {
let _timer = Timer::new("主函数");

// 模拟工作
std::thread::sleep(Duration::from_millis(100));

{
let _inner_timer = Timer::new("内部块");
std::thread::sleep(Duration::from_millis(50));
}

// _timer 在这里被释放,打印总耗时
}

SystemTime

SystemTime 用于获取系统时间:

use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
// 获取当前系统时间
let now = SystemTime::now();

// 获取 Unix 时间戳
match now.duration_since(UNIX_EPOCH) {
Ok(duration) => {
let timestamp = duration.as_secs();
println!("Unix 时间戳: {}", timestamp);
println!("毫秒时间戳: {}", duration.as_millis());
}
Err(e) => println!("错误: {}", e),
}

// 时间计算
let future = now + std::time::Duration::from_secs(60);
println!("一分钟后的时间: {:?}", future);

// 计算与当前时间的差
match future.duration_since(SystemTime::now()) {
Ok(duration) => println!("距离未来时间还有: {:?}", duration),
Err(e) => println!("时间已经过去: {:?}", e.duration()),
}
}

Instant vs SystemTime 的区别

类型用途特点
Instant测量时间间隔单调递增,不受系统时间调整影响
SystemTime获取实际日期时间可能受系统时间调整影响

网络编程基础(std::net)

std::net 提供了基本的网络编程功能,支持 TCP 和 UDP 协议。对于高性能异步网络编程,建议使用 tokio::net

TCP 服务器

use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::thread;

fn handle_client(mut stream: TcpStream) {
let mut buffer = [0; 1024];

// 读取客户端数据
match stream.read(&mut buffer) {
Ok(size) if size > 0 => {
println!("收到 {} 字节", size);

// 回显数据
stream.write_all(&buffer[..size]).unwrap();
}
_ => {}
}
}

fn main() -> std::io::Result<()> {
// 绑定监听地址
let listener = TcpListener::bind("127.0.0.1:8080")?;
println!("服务器启动,监听 127.0.0.1:8080");

// 接受连接
for stream in listener.incoming() {
match stream {
Ok(stream) => {
println!("新连接: {}", stream.peer_addr()?);

// 为每个连接创建新线程
thread::spawn(|| {
handle_client(stream);
});
}
Err(e) => {
eprintln!("连接失败: {}", e);
}
}
}

Ok(())
}

TCP 客户端

use std::net::TcpStream;
use std::io::{Read, Write};

fn main() -> std::io::Result<()> {
// 连接服务器
let mut stream = TcpStream::connect("127.0.0.1:8080")?;
println!("已连接到服务器");

// 发送数据
let message = b"Hello, Server!";
stream.write_all(message)?;
println!("已发送: {}", String::from_utf8_lossy(message));

// 接收响应
let mut buffer = [0; 1024];
let size = stream.read(&mut buffer)?;
println!("收到响应: {}", String::from_utf8_lossy(&buffer[..size]));

Ok(())
}

UDP 通信

use std::net::UdpSocket;
use std::io;

fn main() -> io::Result<()> {
// 绑定套接字
let socket = UdpSocket::bind("127.0.0.1:8080")?;
println!("UDP 服务器监听 127.0.0.1:8080");

// 接收数据
let mut buf = [0; 1024];
let (amt, src) = socket.recv_from(&mut buf)?;
println!("从 {} 收到 {} 字节", src, amt);
println!("内容: {}", String::from_utf8_lossy(&buf[..amt]));

// 发送响应
socket.send_to(b"收到消息", src)?;

Ok(())
}

// UDP 客户端
fn udp_client() -> io::Result<()> {
let socket = UdpSocket::bind("127.0.0.1:0")?; // 随机端口

// 发送数据
socket.send_to(b"Hello UDP", "127.0.0.1:8080")?;

// 接收响应
let mut buf = [0; 1024];
let (amt, src) = socket.recv_from(&mut buf)?;
println!("从 {} 收到: {}", src, String::from_utf8_lossy(&buf[..amt]));

Ok(())
}

IP 地址处理

use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};

fn main() {
// 解析 IP 地址
let local: IpAddr = "127.0.0.1".parse().unwrap();
let local_v6: IpAddr = "::1".parse().unwrap();

println!("IPv4: {}", local);
println!("IPv6: {}", local_v6);

// 创建 IP 地址
let v4 = Ipv4Addr::new(127, 0, 0, 1);
let v6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);

println!("手动创建 IPv4: {}", v4);
println!("手动创建 IPv6: {}", v6);

// 特殊地址
println!("本机地址: {}", Ipv4Addr::LOCALHOST);
println!("任意地址: {}", Ipv4Addr::UNSPECIFIED);
println!("广播地址: {}", Ipv4Addr::BROADCAST);

// Socket 地址(IP + 端口)
let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
println!("Socket 地址: {}", addr);

let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
println!("手动创建 Socket 地址: {}", addr);
}

小结

本章我们学习了 Rust 标准库中常用的模块:

  1. std::fs:文件系统操作,包括文件读写、目录操作、元数据获取
  2. std::path:跨平台路径处理,Path 和 PathBuf 的使用
  3. std::env:环境变量、命令行参数、当前目录等
  4. std::process:进程管理,运行外部命令
  5. std::time:时间测量和持续时间处理
  6. std::net:基础网络编程,TCP 和 UDP

这些模块是 Rust 日常开发中的基础工具,掌握它们对于编写实用程序非常重要。

练习

  1. 编写一个程序,递归遍历目录并统计各类文件的数量
  2. 实现一个简单的配置文件读取器,支持环境变量替换
  3. 使用 std::process 实现一个简单的管道命令执行器
  4. 编写一个 TCP echo 服务器,支持多个客户端同时连接

参考资料