为什么一次扫描耗时需要18秒,有木有办法优化呢?
use std::env;
use tokio::{
io::{self, AsyncReadExt},
net::TcpStream,
time,
};
#[tokio::main]
async fn main() {
let arg = env::args().skip(1);
let host = match arg.last() {
Some(x) => x,
None => "127.0.0.1".to_string(),
};
let host = host.as_str();
println!("正在扫描端口连接...{}", host);
let start = tokio::time::Instant::now();
// 18s
let mut handles = Vec::new();
for port in 1..=65535 {
handles.push(time::timeout(
time::Duration::from_millis(500),
TcpStream::connect((host, port)),
));
}
for h in handles {
if let Ok(Ok(t)) = h.await {
println!("{}", t.peer_addr().unwrap());
}
}
println!("运行时间: {}秒", start.elapsed().as_secs_f32());
println!("按回车关闭...");
let mut buf = Vec::new();
io::stdin().read_buf(&mut buf).await.unwrap();
}
package main
import (
"fmt"
"net"
"os"
"sync"
"time"
)
func main() {
host := "localhost"
args := os.Args
if len(args) == 2 {
host = args[1]
}
waitGroup := sync.WaitGroup{}
start := time.Now()
fmt.Printf("正在扫描端口连接...%s\n", host)
for i := 0; i < 65535; i++ {
waitGroup.Add(1)
go func(i int) {
connect(fmt.Sprintf("%s:%d", host, i))
waitGroup.Done()
}(i)
}
waitGroup.Wait()
fmt.Println(time.Since(start))
fmt.Println("输入回车关闭...")
fmt.Scanln()
}
func connect(addr string) {
timeout := make(chan bool, 1)
go func() {
time.Sleep(500 * time.Millisecond)
timeout <- true
}()
ch := make(chan bool, 1)
go func() {
conn, err := net.Dial("tcp", addr)
if err != nil {
// fmt.Println("连接失败: ", addr)
ch <- false
return
}
defer conn.Close()
ch <- true
}()
select {
case ok := <-ch:
if ok {
fmt.Println("端口正常:", addr)
}
case <-timeout:
}
}
1
共 8 条评论, 1 页
评论区
写评论好吧,感谢指教
👇
Bai-Jinlin: 你传进去(&str,u16)的时候有引用满足不了spwan的'static约束,你用format就是创建了个没有借用的String满足了'static呀,所以我说就是这个没有什么奇怪的地方
--
👇
byeblack: 不是说Tokio啦,https://blog.rust-lang.org/2022/01/13/Rust-1.58.0.html#captured-identifiers-in-format-strings 在这里如果我传值进去就要想办法解决变量host的借用问题,但format宏通过标识符拿到变量,我可以直接将变量传递进去...
--
👇
Bai-Jinlin: 哪里奇怪了?https://docs.rs/tokio/latest/tokio/net/trait.ToSocketAddrs.html
--
👇
byeblack: 非常感谢Grobycn,我又发现个奇怪的事... 1.60.0
你这样 for x in work { do(x).await } 的写法是串行的不会并发执行
用 future::join 并发执行 65535 个请求就快很多
你传进去(&str,u16)的时候有引用满足不了spwan的'static约束,你用format就是创建了个没有借用的String满足了'static呀,所以我说就是这个没有什么奇怪的地方
--
👇
byeblack: 不是说Tokio啦,https://blog.rust-lang.org/2022/01/13/Rust-1.58.0.html#captured-identifiers-in-format-strings 在这里如果我传值进去就要想办法解决变量host的借用问题,但format宏通过标识符拿到变量,我可以直接将变量传递进去...
--
👇
Bai-Jinlin: 哪里奇怪了?https://docs.rs/tokio/latest/tokio/net/trait.ToSocketAddrs.html
--
👇
byeblack: 非常感谢Grobycn,我又发现个奇怪的事... 1.60.0
不是说Tokio啦,https://blog.rust-lang.org/2022/01/13/Rust-1.58.0.html#captured-identifiers-in-format-strings 在这里如果我传值进去就要想办法解决变量host的借用问题,但format宏通过标识符拿到变量,我可以直接将变量传递进去...
--
👇
Bai-Jinlin: 哪里奇怪了?https://docs.rs/tokio/latest/tokio/net/trait.ToSocketAddrs.html
--
👇
byeblack: 非常感谢Grobycn,我又发现个奇怪的事... 1.60.0
哪里奇怪了?https://docs.rs/tokio/latest/tokio/net/trait.ToSocketAddrs.html
--
👇
byeblack: 非常感谢Grobycn,我又发现个奇怪的事... 1.60.0
非常感谢Grobycn,我又发现个奇怪的事... 1.60.0
--
👇
Grobycn: rust 程序没有并发,实际上相当于,
timeout
创建的Future
并没有放入后台调度, 而是后面的for
循环里面一个一个按顺序运行。解决办法: 用
tokio::spawn
放入后台运行原来如此,非常感谢! 加了timeout,把spawn给忘了... 效果立竿见影,哈哈 因为现在tokio还不支持数组join_all,futures又不想用,所以有些错愕。
rust 程序没有并发,实际上相当于,
timeout
创建的Future
并没有放入后台调度, 而是后面的for
循环里面一个一个按顺序运行。解决办法: 用
tokio::spawn
放入后台运行