主机论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 219|回复: 9

写了个优选IP程序

[复制链接]

3

主题

30

回帖

95

积分

注册会员

Rank: 2

积分
95
发表于 2024-11-28 23:16:22 | 显示全部楼层 |阅读模式
本帖最后由 niconiconi 于 2024-11-28 23:20 编辑

写了个优选IP程序,实测50W个IP ping 4次取平均值,获取延迟最低前十只需要几秒钟,会动手的mjj自己编译,刚开始学有点糙

下载地址 https://drive.kamibook.com/raw/ipopt.7z

./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. while buf_reader.read_line(&mut line).unwrap() > 0 {
  89. let ip = line.trim();
  90. ips.push(ip.to_string());
  91. line.clear();
  92. }
  93. Ok(ips)
  94. }


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

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

使用道具 举报

0

主题

408

回帖

1106

积分

金牌会员

Rank: 6Rank: 6

积分
1106
发表于 2024-11-28 23:17:42 | 显示全部楼层
大佬怎么用呢?
回复

使用道具 举报

37

主题

395

回帖

1149

积分

金牌会员

Rank: 6Rank: 6

积分
1149
发表于 2024-11-28 23:18:43 | 显示全部楼层
不是有7Z吗 ,下载下来用啊
回复

使用道具 举报

3

主题

30

回帖

95

积分

注册会员

Rank: 2

积分
95
 楼主| 发表于 2024-11-28 23:27:36 | 显示全部楼层
由于多线程并发,会创建大量任务,这也是为什么在几秒钟内完成,所以cpu 内存会占用很大,50W占用内存800M
回复

使用道具 举报

2

主题

136

回帖

492

积分

中级会员

Rank: 3Rank: 3

积分
492
发表于 2024-11-29 00:00:51 | 显示全部楼层
loc还有会rust的,罕见
回复

使用道具 举报

3

主题

30

回帖

95

积分

注册会员

Rank: 2

积分
95
 楼主| 发表于 2024-11-29 00:26:27 | 显示全部楼层
skysf 发表于 2024-11-29 00:00
loc还有会rust的,罕见

loc人才济济
回复

使用道具 举报

28

主题

1万

回帖

3万

积分

论坛元老

Rank: 8Rank: 8

积分
36112
发表于 2024-11-29 00:00:00 | 显示全部楼层
skysf 发表于 2024-11-29 00:00
loc还有会rust的,罕见


没什么罕见的,rust跟其他一样都是用库而已,你说看到.cpp .c那才叫罕见
回复

使用道具 举报

2

主题

32

回帖

134

积分

注册会员

Rank: 2

积分
134
发表于 2024-11-29 00:30:03 | 显示全部楼层
编译不通过
回复

使用道具 举报

3

主题

30

回帖

95

积分

注册会员

Rank: 2

积分
95
 楼主| 发表于 2024-11-29 00:00:00 | 显示全部楼层
弟弟不爱吃饭 发表于 2024-11-29 00:30
编译不通过

错误截图
回复

使用道具 举报

130

主题

2571

回帖

6774

积分

论坛元老

Rank: 8Rank: 8

积分
6774
发表于 2024-11-29 00:30:43 | 显示全部楼层
loc果然高手如云啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|主机论坛

GMT+8, 2025-7-13 16:05 , Processed in 0.080626 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表