首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用 Rust 打造一个简单的 CLI IP 扫描工具

用 Rust 打造一个简单的 CLI IP 扫描工具

作者头像
不吃草的牛德
发布2026-04-23 11:14:14
发布2026-04-23 11:14:14
810
举报
文章被收录于专栏:RustRust

Rust 是一门以安全和性能著称的现代编程语言,非常适合开发命令行工具。本教程将带你用 Rust 编写一个简单的 CLI IP 扫描工具,扫描局域网内的在线设备。即使你是 Rust 新手,也能通过分步指导完成项目。


想象一下,你想快速知道家里的 Wi-Fi 网络中有哪些设备在线,比如电脑、手机或路由器。IP 扫描工具就能帮你实现!本教程将用 Rust 开发一个简单的命令行 IP 扫描工具,学习 Rust 的基本语法、项目管理和常用库。Rust 的内存安全和高效性能让它成为开发 CLI 工具的绝佳选择。准备好动手了吗?让我们开始!

环境准备首先,我们需要搭建 Rust 开发环境。以下是具体步骤:

安装 Rust: 访问 Rust 官网,下载并安装 rustup。 在终端运行以下命令安装 Rust:

代码语言:javascript
复制
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

安装完成后,运行 rustc --version 和 cargo --version 检查是否成功(Cargo 是 Rust 的构建工具和包管理器)。

创建项目:

打开终端,创建一个新项目

代码语言:javascript
复制
cargo new ip-scanner
cd ip-scanner

这会生成一个包含 Cargo.toml(项目配置文件)和 src/main.rs(主程序文件)的项目目录。

安装代码编辑器:

推荐使用 Visual Studio Code 配合 Rust 插件(Rust Analyzer),提供语法高亮和代码补全。


核心功能设计

我们 IP 扫描工具目标简单:扫描用户指定的 IP 地址范围,检查哪些主机在线(通过 ping)。主要功能包括:

  • 命令行参数:用户输入 IP 范围(如 192.168.1.1-192.168.1.10)。
  • 异步扫描:快速检查多个 IP 是否在线。
  • 错误处理:优雅处理网络超时或无效输入。

我们将使用以下 Rust 库:

  • clap:解析命令行参数,简单易用。
  • tokio:实现异步网络操作,提升扫描效率。
  • ping-rs:执行 ping 操作,检查主机是否在线。

在 Cargo.toml 中添加依赖:

代码语言:javascript
复制
[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 范围。代码如下:

代码语言:javascript
复制
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,
}

解释:

  • clap::Parser 自动解析命令行参数。
  • Args 结构体定义一个 range 参数,表示 IP 范围。
  • Rust 的内存安全确保 range 字符串在解析时不会引发未定义行为。

步骤 2:解析 IP 范围将输入的 IP 范围拆分为起始和结束 IP,生成需要扫描的 IP 列表:

代码语言:javascript
复制
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
}

解释:

  • parse_ip_range 将 192.168.1.1-192.168.1.10 解析为 IP 列表。
  • Rust 的 Vec 确保内存安全,避免越界访问。
  • 使用 panic! 处理无效输入,简单直接(生产环境可替换为更优雅的错误处理)。

步骤 3:异步扫描 IP使用 tokio 和 ping-rs 异步 ping 每个 IP:

代码语言:javascript
复制
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),
    }
}

解释:

  • tokio::task 提供异步运行时,允许并发 ping 多个 IP。
  • ping-rs 执行 ping 操作,返回是否成功。
  • Rust 的错误处理(match 和 Result)确保程序不会因网络错误崩溃。

步骤 4:主函数整合将所有功能整合到 main 函数:

代码语言:javascript
复制
#[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);
            }
        }
    }
}

解释:

  • #[tokio::main] 启用异步运行时。

  • 使用 task::spawn 并发扫描 IP,提升效率。
  • Rust 的所有权系统确保 ips 和 tasks 在使用时不会引发内存问题。

完整代码请复制到 src/main.rs,确保 Cargo.toml 已添加依赖。

运行与测试

编译与运行:

  • 在项目目录运行:

代码语言:javascript
复制
cargo run -- --range 192.168.1.1-192.168.1.10

测试:

  • 在家用网络中运行,检查是否能发现路由器(如 192.168.1.1)或电脑。
  • 确保有网络权限,可能需以管理员身份运行(Windows 用 cmd 以管理员启动,Linux 用 sudo)。

预期输出

代码语言:javascript
复制
IP 192.168.1.1 is online
IP 192.168.1.5 is online

常见问题与调试

  1. 依赖安装失败:
    • 确保网络连接正常,运行 cargo clean 后重试 cargo build。
    • 检查 Rust 版本:rustup update。
  2. 权限问题:
    • ping 需要管理员权限,Linux 上用 sudo cargo run,Windows 打开管理员命令提示符。
  3. IP 范围无效:
    • 确保输入格式正确,如 192.168.1.1-192.168.1.10。
    • 检查 IP 是否在同一子网。

总结与扩展通过这个项目,你学会了 Rust 的基本语法(结构体、枚举)、Cargo 项目管理、clap 解析参数、tokio 异步编程,以及 Rust 的内存安全特性。是不是很有成就感?扩展任务:

  • 添加端口扫描:修改代码,加入端口参数,使用 std::net::TcpStream 检查特定端口是否开放。
  • 导出结果:将扫描结果保存到 CSV 文件,使用 std::fs 模块。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust火箭工坊 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档