UI设计 薇晓朵数字商城

 找回密碼
 加入我們

優選IP程序

[複製鏈接]
小猪哼囔 發表於 2024-12-7 00:29:09 | 顯示全部樓層 |閱讀模式
優選IP程序,實測50W個IP ping 4次取平均值,獲取延遲最低前十只需要幾秒鐘,會動手的自己編譯

下載地址
遊客,如果您要查看本帖隱藏內容請回復


./ipopt.exe ipv4 ip.txt

ip.txt內容 示例 1.1.1.1/24  壹行壹個



  1. use std::{
  2.     result,
  3.     env,
  4.     net::IpAddr,
  5.     time::Duration,
  6.     io::BufRead,
  7.     collections::HashMap,
  8. };
  9. use futures::future::join_all;
  10. use rand::random;
  11. use surge_ping::{Client, Config, IcmpPacket, PingIdentifier, PingSequence, ICMP};
  12. use tokio::time;
  13. use ipnet::{Ipv4Net, Ipv6Net};

  14. #[tokio::main]
  15. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  16.     let args: Vec<String> = env::args().collect();
  17.     let ips = get_ip_from_file(&args[2]).await?;
  18.     let ipaddrs = get_ip_range(&args[1], ips).await?;
  19.     let client_v4 = Client::new(&Config::default())?;
  20.     let client_v6 = Client::new(&Config::builder().kind(ICMP::V6).build())?;
  21.     let mut tasks = Vec::new();

  22.     for ip in &ipaddrs {
  23.         match ip.parse() {
  24.             Ok(IpAddr::V4(addr)) => {
  25.                 tasks.push(tokio::spawn(ping(client_v4.clone(), IpAddr::V4(addr))))

  26.             }
  27.             Ok(IpAddr::V6(addr)) => {
  28.                 tasks.push(tokio::spawn(ping(client_v6.clone(), IpAddr::V6(addr))))
  29.             }
  30.             Err(e) => println!("{} parse to ipaddr error: {}", ip, e),
  31.         }
  32.     }
  33.     let results: Vec<_> = join_all(tasks).await.into_iter().filter_map(Result::ok).collect();
  34.     let mut ip_map = HashMap::new();

  35.     for result in results {
  36.         match result {
  37.             Ok((ip, delay)) => {
  38.                 ip_map.insert(ip, delay);
  39.             }
  40.             Err(e) => {
  41.                 eprintln!("Error occurred: {:?}", e);
  42.             }
  43.         }
  44.     }
  45.     let top_10: Vec<_> = ip_map.into_iter()
  46.     .filter(|(_, delay)| delay.as_millis() > 0)
  47.     .collect::<Vec<_>>()
  48.     .into_iter()
  49.     .sorted_by(|(_, delay1), (_, delay2)| delay1.cmp(delay2))
  50.     .take(10)
  51.     .collect();

  52.     for (ip, delay) in top_10 {
  53.         println!("{} {:?}", ip, delay.as_millis());
  54.     }
  55.     Ok(())
  56. }
  57. async fn ping(client: Client, addr: IpAddr) -> Result<(IpAddr, Duration), Box<dyn std::error::Error + Send + 'static>> {
  58.     let payload = [0; 56];
  59.     let mut pinger = client.pinger(addr, PingIdentifier(random())).await;
  60.     let mut interval = time::interval(Duration::from_secs(1));
  61.     let mut delays = Vec::new();

  62.     for idx in 0..4 {
  63.         interval.tick().await;
  64.         match pinger.ping(PingSequence(idx), &payload).await {
  65.             Ok((IcmpPacket::V4(_packet), dur)) => {
  66.                 delays.push(dur);
  67.             }
  68.             Ok((IcmpPacket::V6(_packet), dur)) => {
  69.                 delays.push(dur);
  70.             }
  71.             Err(_e) => {
  72.             }
  73.         };
  74.     }
  75.     let average_delay = if !delays.is_empty() {
  76.         let total: Duration = delays.iter().sum();
  77.         total / delays.len() as u32
  78.     } else {
  79.         Duration::new(0, 0)
  80.     };
  81.     Ok((addr, average_delay))
  82. }

  83. async fn get_ip_from_file(file_path: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
  84.     let mut ips = Vec::new();
  85.     let file = std::fs::File::open(file_path)?;
  86.     let mut buf_reader = std::io::BufReader::new(file);
  87.     let mut line = String::new();
  88.    
  89.     while buf_reader.read_line(&mut line).unwrap() > 0 {
  90.         let ip = line.trim();
  91.         ips.push(ip.to_string());
  92.         line.clear();
  93.     }
  94.     Ok(ips)
  95. }


  96. async fn get_ip_range(ip_type: &str, ips: Vec<String>) -> result::Result<Vec<String>, Box<dyn std::error::Error>> {
  97.     let mut ip_subnets = Vec::new();

  98.     match ip_type {
  99.         "ipv4" => {
  100.             for ip in ips {
  101.                 let net: Ipv4Net = ip.parse().unwrap();
  102.                 let subnets = net.subnets(32).expect("PrefixLenError: new prefix length cannot be shorter than existing");
  103.                 for (_i, n) in subnets.enumerate() {
  104.                     ip_subnets.push(n.to_string());
  105.                 }
  106.             }
  107.         }
  108.         "ipv6" => {
  109.             for ip in ips {
  110.                 let net: Ipv6Net = ip.parse().unwrap();
  111.                 let subnets = net.subnets(128).expect("PrefixLenError: new prefix length cannot be shorter than existing");
  112.                 for (_i, n) in subnets.enumerate() {
  113.                     ip_subnets.push(n.to_string());
  114.                 }
  115.             }
  116.         }
  117.         _ => {
  118.             return Err(Box::new(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Invalid IP type")));
  119.         }
  120.     }
  121.     let ip_range: Vec<String> =  ip_subnets.into_iter().map(|subnet: String| subnet.split('/').next().unwrap().to_string()).collect();
  122.     Ok(ip_range)
  123. }
複製代碼


回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 加入我們

本版積分規則

备案权重域名预定

點基跨境

GMT+8, 2025-1-22 12:25

By DZ X3.5

QQ

快速回復 返回頂部 返回列表