我试图构建一个简单的TCP端口扫描器来练习学习Go中的并发性。我正在关注这个YouTube视频(https://www.youtube.com/watch?v=LvgVSSpwND8),介绍如何使用通道和Goroutines在Go中实现“工人池”。我尝试利用视频中的想法,并实现了TCP扫描器功能,如下所示:
func worker(ports <-chan int, results chan<- string) {
for p := range ports {
address := fmt.Sprintf("127.0.0.1:%d", p)
conn, err := net.Dial("tcp", address)
if err != nil {
results <- fmt.Sprintf("Port %d is closed: %s", p, err.Error())
} else {
conn.Close()
results <- fmt.Sprintf("Port %d is open", p)
}
}
}
func main() {
ports := make(chan int, 100)
results := make(chan string, 100)
for i := 0; i < cap(ports); i++ {
go worker(ports, results)
}
for j := 1; j <= 65535; j++ {
ports <- j
}
close(ports)
for k := 1; k <= 65535; k++ {
fmt.Println(<-results)
}
close(results)
}
字符串
我期望它能以随机的顺序慢慢打印出结果,就像YouTube视频中那样。但控制台上没有任何输出。我尝试调试通道,工作函数从端口通道接收端口号,但似乎没有任何东西返回到结果通道。
1条答案
按热度按时间q9rjltbz1#
这是因为你没有在你应该听的时候听结果。
写入
ports
的for循环将在前100个请求后阻塞,因为这是该通道的大小,并且所有的goroutine将阻塞等待写入results
通道,因为没有goroutine从它阅读。你可以通过监听一个单独的goroutine来修复它:
字符串