network 1.0.0

Network Basic Library: Network Basic Operations, WiFi Definition, Linux WPA Implementation
Documentation

network

一个面向 Rust 的网络工具库,主要提供以下能力:

  • 枚举本机物理网卡与基础网络状态
  • 获取本机 IP、MAC、默认联网网卡等信息
  • 监听网卡上下线变化
  • 在 Linux 下启用/禁用网卡
  • 通过可选 feature 提供 Wi-Fi 管理能力
  • 在 Linux 下基于 wpa_supplicant 管理无线网络

这个项目目前更偏向库(library)而不是独立命令行程序。

特性概览

通用网络能力

默认特性下即可使用:

  • 获取网卡列表:utils::ifaces
  • 获取原始网卡信息:utils::get_source_ifaces
  • 获取本机 IP:utils::get_local_ip / utils::get_local_ips
  • 获取 MAC 地址:utils::get_mac_addr / utils::get_physical_mac
  • 判断当前是否联网:utils::check_online / utils::is_online
  • 获取局域网连接与在线状态:utils::lan_is_ok
  • 监听网卡事件:utils::listen_change
  • Linux 下启用/禁用网卡:utils::enable

Wi-Fi 能力

启用 wifi feature 后可使用统一的 Wi-Fi trait 和数据结构:

  • wifi::IWifi
  • wifi::ScanResult
  • wifi::NetworkListResult
  • wifi::Status

WPA / wpa_supplicant 能力

启用 wpa feature 且运行在 Linux 时,可通过 Unix Domain Socket 与 wpa_supplicant 通信:

  • 自动发现无线网卡并初始化:wifi::linux::WpaSupplicant::auto_setup
  • 指定网卡初始化:wifi::linux::WpaSupplicant::new
  • 扫描附近 Wi-Fi
  • 查看已保存网络
  • 连接 / 断开 / 重连 Wi-Fi
  • 选择指定 network id
  • 保存或移除 wpa_supplicant 配置

平台说明

  • 通用网卡信息读取依赖 netdevif-watch,核心逻辑以跨平台接口为主
  • linux 模块仅在 target_os = "linux" 下编译
  • wpa 模块仅在 Linux + feature = "wpa" 下可用
  • 当前 Wi-Fi 管理实现实际依赖 Linux 的 wpa_supplicant socket,Windows 下未实现对应控制逻辑

Feature 说明

Cargo.toml 中当前提供两个可选 feature:

[features]
default = []
wifi = ["async-trait"]
wpa = ["libc", "config", "tempfile"]

建议按场景启用:

  • 只使用基础网络能力:不需要额外 feature
  • 只依赖 Wi-Fi trait / DTO:wifi
  • 使用 Linux wpa_supplicant 控制能力:wifi,wpa

示例:

cargo add network

如果以本地路径依赖:

[dependencies]
network = { path = ".", features = ["wifi", "wpa"] }

依赖环境

当你使用 wpa 能力时,需要保证:

  • 系统为 Linux
  • 已安装并启动 wpa_supplicant
  • 存在对应网卡的控制 socket,例如 /var/run/wpa_supplicant/wlan0
  • 当前进程对该 socket 具有访问权限

项目内部默认会尝试连接类似下面的路径:

/var/run/wpa_supplicant/<iface>

快速开始

1. 获取网卡列表

use network::utils;

fn main() {
    let ifaces = utils::ifaces();
    for iface in ifaces {
        println!(
            "{} {} wifi={} up={} ipv4={}",
            iface.name, iface.friendly_name, iface.is_wifi, iface.is_up, iface.ipv4_addr
        );
    }
}

2. 获取本机 IP 与 MAC

use network::utils;

fn main() -> anyhow::Result<()> {
    let ip = utils::get_local_ip()?;
    let mac = utils::get_mac_addr()?;

    println!("local ip: {ip}");
    println!("mac: {mac}");
    Ok(())
}

3. 监听网络变化

use network::utils;

fn on_change(is_up: bool) {
    println!("network changed, is_up={is_up}");
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let _handle = utils::listen_change(on_change)?;

    loop {
        tokio::time::sleep(std::time::Duration::from_secs(60)).await;
    }
}

4. Linux 下启用或禁用网卡

#[cfg(target_os = "linux")]
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    network::utils::enable("eth0", true).await?;
    Ok(())
}

Wi-Fi 使用示例

下面示例需要启用 features = ["wifi", "wpa"],并运行在 Linux。

初始化 wpa_supplicant 客户端

use network::wifi::{IWifi, linux::WpaSupplicant};

fn on_wifi_event(evt: String) {
    println!("wifi event: {evt}");
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(Some(on_wifi_event)).await?;

    let status = wifi.status().await?;
    println!("{status:?}");
    Ok(())
}

扫描附近 Wi-Fi

use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;
    let results = wifi.scan().await?;

    for item in results {
        println!(
            "ssid={} signal={} level={} encrypted={}",
            item.ssid_name,
            item.signal,
            item.to_level(),
            item.is_encrypted
        );
    }

    Ok(())
}

连接 Wi-Fi

use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;

    wifi.connect("MyWiFi".to_string(), "12345678".to_string()).await?;

    Ok(())
}

开放网络可传空密码:

wifi.connect("OpenWiFi".to_string(), "".to_string()).await?;

查看已保存网络

use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;
    let networks = wifi.get_networks().await?;

    for item in networks {
        println!(
            "id={} ssid={} connected={} disabled={}",
            item.network_id,
            item.ssid,
            item.is_connected(),
            item.is_disable()
        );
    }

    Ok(())
}

切换、断开与移除网络

use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;

    let _ = wifi.select_id(0).await?;
    wifi.disconnect().await?;
    wifi.reconnect().await?;
    wifi.remove(0).await?;

    Ok(())
}

主要数据结构

IfaceDto

表示网卡的基础信息:

  • index: 网卡索引
  • name: 系统网卡名,如 eth0wlan0
  • friendly_name: 友好名称
  • is_wifi: 是否为无线网卡
  • mac_addr: MAC 地址
  • ipv4_addr: IPv4 地址
  • ipv6_addr: IPv6 地址
  • has_dns: 是否存在 DNS 配置
  • cur_used: 是否为当前默认使用网卡
  • is_up: 是否启用

NetInfoDto

  • ifaces: 网卡列表
  • connected: 是否已连接网络

ScanResult

  • bissid_mac: AP 的 BSSID / MAC
  • frequency: 频段频率
  • signal: 信号强度(dBm)
  • flags: 扫描标志
  • is_encrypted: 是否加密
  • ssid_name: Wi-Fi 名称

NetworkListResult

  • network_id: wpa_supplicant 中的网络 ID
  • ssid: Wi-Fi 名称
  • flags: 状态标记
  • bssid: 关联 BSSID

设计说明

  • 底层网卡枚举基于 netdev
  • 网络变化监听基于 if-watch
  • 异步运行时基于 tokio
  • Wi-Fi 控制通过异步 channel + wpa_supplicant socket 完成
  • 扫描结果和事件结果会经过简单封装,便于上层业务直接使用

注意事项

  • utils::check_online() 当前通过 UDP 连接 114.114.114.114:53 判断外网连通性,这更像“是否可以访问外部网络”的近似判断
  • utils::ifaces() 会过滤回环网卡、Docker 网卡、p2p0 以及非物理网卡
  • WpaSupplicant::auto_setup() 会选择扫描到的第一个无线网卡
  • 使用 wpa 能力时,运行权限、socket 权限和系统网络配置都会影响结果
  • README 中的示例基于当前代码接口编写,如后续 API 调整请同步更新

开发与检查

cargo check
cargo check --features wifi
cargo check --features "wifi wpa"

许可证

本项目基于 MIT License 发布。