Rust网络状态监控库netstat2的使用,netstat2提供高效网络连接统计与端口监控功能

Rust网络状态监控库netstat2的使用

netstat2是一个跨平台库,用于检索网络套接字信息。它通过使用低级操作系统API而不是命令行工具来实现高效性能,并提供统一的接口和返回数据结构。

安装

在Cargo.toml中添加依赖:

[dependencies]
netstat2 = "0.11"

示例代码

以下是内容中提供的示例:

use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    let sockets_info = get_sockets_info(af_flags, proto_flags)?;
    
    for si in sockets_info {
        match si.protocol_socket_info {
            ProtocolSocketInfo::Tcp(tcp_si) => println!(
                "TCP {}:{} -> {}:{} {:?} - {}",
                tcp_si.local_addr,
                tcp_si.local_port,
                tcp_si.remote_addr,
                tcp_si.remote_port,
                si.associated_pids,
                tcp_si.state
            ),
            ProtocolSocketInfo::Udp(udp_si) => println!(
                "UDP {}:{} -> *:* {:?}",
                udp_si.local_addr, udp_si.local_port, si.associated_pids
            ),
        }
    }

    Ok(())
}

完整示例

以下是一个更完整的网络状态监控示例,包含更多功能展示:

use netstat2::{
    get_sockets_info, AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo, 
    TcpState, SocketInfo
};
use std::error::Error;

// 网络连接统计结构体
struct ConnectionStats {
    total: usize,
    tcp: usize,
    udp: usize,
    established: usize,
    listening: usize,
}

fn main() -> Result<(), Box<dyn Error>> {
    // 设置要查询的协议类型
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    // 获取所有套接字信息
    let sockets_info = get_sockets_info(af_flags, proto_flags)?;
    
    // 初始化统计
    let mut stats = ConnectionStats {
        total: 0,
        tcp: 0,
        udp: 0,
        established: 0,
        listening: 0,
    };

    // 遍历所有套接字并统计信息
    for si in sockets_info {
        stats.total += 1;
        
        match si.protocol_socket_info {
            ProtocolSocketInfo::Tcp(tcp_si) => {
                stats.tcp += 1;
                
                // 统计TCP状态
                match tcp_si.state {
                    TcpState::Established => stats.established += 1,
                    TcpState::Listen => stats.listening += 1,
                    _ => (),
                }
                
                print_tcp_info(&si, &tcp_si);
            }
            ProtocolSocketInfo::Udp(udp_si) => {
                stats.udp += 1;
                print_udp_info(&si, &udp_si);
            }
        }
    }

    // 打印统计信息
    println!("\n=== 网络连接统计 ===");
    println!("总连接数: {}", stats.total);
    println!("TCP连接数: {}", stats.tcp);
    println!("  - 已建立: {}", stats.established);
    println!("  - 监听中: {}", stats.listening);
    println!("UDP连接数: {}", stats.udp);

    Ok(())
}

// 打印TCP连接信息
fn print_tcp_info(si: &SocketInfo, tcp_si: &netstat2::TcpSocketInfo) {
    println!(
        "TCP {}:{} -> {}:{} (PID: {:?}) - 状态: {:?}",
        tcp_si.local_addr,
        tcp_si.local_port,
        tcp_si.remote_addr,
        tcp_si.remote_port,
        si.associated_pids,
        tcp_si.state
    );
}

// 打印UDP连接信息
fn print_udp_info(si: &SocketInfo, udp_si: &netstat2::UdpSocketInfo) {
    println!(
        "UDP {}:{} (PID: {:?})",
        udp_si.local_addr,
        udp_si.local_port,
        si.associated_pids
    );
}

实现细节

  • 在Windows上,该库使用GetExtendedTcpTable和GetExtendedUdpTable (iphlpapi)
  • 在Linux和Android上,它使用NETLINK_INET_DIAG协议并通过遍历procfs进行pid查找
  • 在macOS和iOS上,它使用proc_pidfdinfo

许可证

可选择以下两种许可证之一:

  • Apache License, Version 2.0
  • MIT license

netstat2库提供了一种高效的方式来监控网络连接状态和端口使用情况,适用于需要网络监控功能的Rust应用程序开发。


1 回复

Rust网络状态监控库netstat2使用指南

简介

netstat2是一个高效的Rust库,用于监控网络连接状态和端口使用情况。它提供了跨平台的网络统计功能,可以替代系统自带的netstat命令,并以编程方式获取网络连接信息。

主要功能

  • 获取所有活跃的网络连接
  • 监控端口使用情况
  • 区分TCP和UDP连接
  • 获取连接相关的进程信息
  • 支持IPv4和IPv6

使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
netstat2 = "0.2"

基本示例

use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo};

fn main() {
    // 获取所有TCP和UDP连接
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    match get_sockets_info(af_flags, proto_flags) {
        Ok(sockets) => {
            for socket in sockets {
                match socket {
                    ProtocolSocketInfo::Tcp(tcp) => {
                        println!("TCP connection: {}:{} -> {}:{} (PID: {:?})", 
                            tcp.local_addr, tcp.local_port, 
                            tcp.remote_addr, tcp.remote_port, 
                            tcp.associated_pids);
                    },
                    ProtocolSocketInfo::Udp(udp) => {
                        println!("UDP connection: {}:{} (PID: {:?})", 
                            udp.local_addr, udp.local_port, 
                            udp.associated_pids);
                    }
                }
            }
        },
        Err(e) => eprintln!("Error: {}", e),
    }
}

监控特定端口

use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags};

fn is_port_in_use(port: u16) -> bool {
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    match get_sockets_info(af_flags, proto_flags) {
        Ok(sockets) => sockets.iter().any(|s| match s {
            ProtocolSocketInfo::Tcp(tcp) => tcp.local_port == port,
            ProtocolSocketInfo::Udp(udp) => udp.local_port == port,
        }),
        Err(_) => false,
    }
}

fn main() {
    let port = 8080;
    if is_port_in_use(port) {
        println!("Port {} is in use!", port);
    } else {
        println!("Port {} is available", port);
    }
}

获取进程网络连接统计

use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo};

fn get_process_connections(pid: u32) {
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    match get_sockets_info(af_flags, proto_flags) {
        Ok(sockets) => {
            println!("Connections for PID {}:", pid);
            for socket in sockets {
                let pids = match &socket {
                    ProtocolSocketInfo::Tcp(tcp) => &tcp.associated_pids,
                    ProtocolSocketInfo::Udp(udp) => &udp.associated_pids,
                };
                
                if pids.contains(&pid) {
                    println!("{:?}", socket);
                }
            }
        },
        Err(e) => eprintln!("Error: {}", e),
    }
}

fn main() {
    get_process_connections(1234); // 替换为你想检查的PID
}

完整示例

以下是一个综合使用netstat2库的完整示例,展示了如何获取网络连接、检查端口使用情况以及监控特定进程的网络活动:

use netstat2::{
    get_sockets_info, 
    AddressFamilyFlags, 
    ProtocolFlags, 
    ProtocolSocketInfo
};

fn main() {
    // 示例1:获取所有网络连接
    println!("=== 所有网络连接 ===");
    list_all_connections();
    
    // 示例2:检查端口是否被占用
    println!("\n=== 端口检查 ===");
    check_ports(&[8080, 3000, 6379]);
    
    // 示例3:监控特定进程的网络活动
    println!("\n=== 进程网络监控 ===");
    monitor_process_connections(std::process::id()); // 监控当前进程
}

/// 列出所有网络连接
fn list_all_connections() {
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    match get_sockets_info(af_flags, proto_flags) {
        Ok(sockets) => {
            for socket in sockets {
                match socket {
                    ProtocolSocketInfo::Tcp(tcp) => {
                        println!("TCP {}:{} -> {}:{} PID:{:?}", 
                            tcp.local_addr, tcp.local_port,
                            tcp.remote_addr, tcp.remote_port,
                            tcp.associated_pids);
                    },
                    ProtocolSocketInfo::Udp(udp) => {
                        println!("UDP {}:{} PID:{:?}",
                            udp.local_addr, udp.local_port,
                            udp.associated_pids);
                    }
                }
            }
        },
        Err(e) => eprintln!("获取连接失败: {}", e),
    }
}

/// 检查一组端口是否被占用
fn check_ports(ports: &[u16]) {
    for &port in ports {
        println!("端口 {}: {}", port, 
            if is_port_in_use(port) { "使用中" } else { "可用" });
    }
}

/// 检查单个端口是否被使用
fn is_port_in_use(port: u16) -> bool {
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    match get_sockets_info(af_flags, proto_flags) {
        Ok(sockets) => sockets.iter().any(|s| match s {
            ProtocolSocketInfo::Tcp(tcp) => tcp.local_port == port,
            ProtocolSocketInfo::Udp(udp) => udp.local_port == port,
        }),
        Err(_) => false,
    }
}

/// 监控特定进程的网络连接
fn monitor_process_connections(pid: u32) {
    let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
    let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
    
    match get_sockets_info(af_flags, proto_flags) {
        Ok(sockets) => {
            let process_sockets: Vec<_> = sockets.into_iter()
                .filter(|s| match s {
                    ProtocolSocketInfo::Tcp(tcp) => tcp.associated_pids.contains(&pid),
                    ProtocolSocketInfo::Udp(udp) => udp.associated_pids.contains(&pid),
                })
                .collect();
            
            println!("进程 {} 有 {} 个活跃连接:", pid, process_sockets.len());
            for socket in process_sockets {
                println!(" - {:?}", socket);
            }
        },
        Err(e) => eprintln!("获取进程连接失败: {}", e),
    }
}

注意事项

  1. 在Linux系统上需要足够的权限才能获取所有连接信息
  2. 不同平台(Windows/Linux/macOS)的实现细节可能有所不同
  3. 频繁调用可能会对系统性能产生一定影响

netstat2库为Rust开发者提供了强大的网络监控能力,特别适合需要程序化网络状态监控的应用场景。

回到顶部