Rust 是一门以安全和性能著称的现代编程语言,非常适合开发命令行工具。本教程将带你用 Rust 编写一个简单的 CLI IP 扫描工具,扫描局域网内的在线设备。即使你是 Rust 新手,也能通过分步指导完成项目。
想象一下,你想快速知道家里的 Wi-Fi 网络中有哪些设备在线,比如电脑、手机或路由器。IP 扫描工具就能帮你实现!本教程将用 Rust 开发一个简单的命令行 IP 扫描工具,学习 Rust 的基本语法、项目管理和常用库。Rust 的内存安全和高效性能让它成为开发 CLI 工具的绝佳选择。准备好动手了吗?让我们开始!
环境准备首先,我们需要搭建 Rust 开发环境。以下是具体步骤:
安装 Rust: 访问 Rust 官网,下载并安装 rustup。 在终端运行以下命令安装 Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh安装完成后,运行 rustc --version 和 cargo --version 检查是否成功(Cargo 是 Rust 的构建工具和包管理器)。
创建项目:
打开终端,创建一个新项目
cargo new ip-scanner
cd ip-scanner这会生成一个包含 Cargo.toml(项目配置文件)和 src/main.rs(主程序文件)的项目目录。
安装代码编辑器:
推荐使用 Visual Studio Code 配合 Rust 插件(Rust Analyzer),提供语法高亮和代码补全。
核心功能设计
我们 IP 扫描工具目标简单:扫描用户指定的 IP 地址范围,检查哪些主机在线(通过 ping)。主要功能包括:
我们将使用以下 Rust 库:
在 Cargo.toml 中添加依赖:
[dependencies]
clap = { version = "4.4", features = ["derive"] }
tokio = { version = "1.32", features = ["full"] }
ping-rs = "0.1"运行 cargo build 下载依赖,准备编码!
代码实现
下面是完整的 Rust 代码实现,分步骤讲解。我们将实现一个命令行工具,接受 IP 范围输入,异步 ping 每个 IP,并输出在线主机。步骤 1:解析命令行参数我们用 clap 解析用户输入的 IP 范围。代码如下:
use clap::Parser;
#[derive(Parser)]
#[command(name = "ip-scanner", about = "A simple IP scanner")]
struct Args {
#[arg(short, long, help = "IP range to scan, e.g., 192.168.1.1-192.168.1.10")]
range: String,
}解释:
步骤 2:解析 IP 范围将输入的 IP 范围拆分为起始和结束 IP,生成需要扫描的 IP 列表:
fn parse_ip_range(range: &str) -> Vec<String> {
let parts: Vec<&str> = range.split('-').collect();
if parts.len() != 2 {
panic!("Invalid IP range format. Use: start_ip-end_ip");
}
let start_ip = parts[0];
let end_ip = parts[1];
let mut ips = Vec::new();
let start_parts: Vec<u8> = start_ip.split('.').map(|s| s.parse().unwrap()).collect();
let end_parts: Vec<u8> = end_ip.split('.').map(|s| s.parse().unwrap()).collect();
// 假设扫描同一子网,最后一位变化
for i in start_parts[3]..=end_parts[3] {
let ip = format!("{}.{}.{}.{}", start_parts[0], start_parts[1], start_parts[2], i);
ips.push(ip);
}
ips
}解释:
步骤 3:异步扫描 IP使用 tokio 和 ping-rs 异步 ping 每个 IP:
use ping_rs::{PingOptions, ping};
use tokio::task;
async fn scan_ip(ip: String) -> (String, bool) {
let options = PingOptions { timeout: 1, ttl: 128, dont_fragment: false };
let result = ping(&ip.parse().unwrap(), Some(options));
match result {
Ok(_) => (ip, true),
Err(_) => (ip, false),
}
}解释:
步骤 4:主函数整合将所有功能整合到 main 函数:
#[tokio::main]
async fn main() {
let args = Args::Parser::parse();
let ips = parse_ip_range(&args.range);
let mut tasks = Vec::new();
for ip in ips {
tasks.push(task::spawn(scan_ip(ip)));
}
for task in tasks {
if let Ok((ip, is_alive)) = task.await {
if is_alive {
println!("IP {} is online", ip);
}
}
}
}解释:
完整代码请复制到 src/main.rs,确保 Cargo.toml 已添加依赖。
运行与测试
编译与运行:
cargo run -- --range 192.168.1.1-192.168.1.10测试:
预期输出
IP 192.168.1.1 is online
IP 192.168.1.5 is online常见问题与调试
总结与扩展通过这个项目,你学会了 Rust 的基本语法(结构体、枚举)、Cargo 项目管理、clap 解析参数、tokio 异步编程,以及 Rust 的内存安全特性。是不是很有成就感?扩展任务: