英文:
Golang worker pool not returning any results
问题
我正在尝试构建一个简单的TCP端口扫描器,以练习在Go语言中学习并发编程。我正在按照这个YouTube视频(https://www.youtube.com/watch?v=LvgVSSpwND8)中的指南,使用通道和Goroutines实现Go语言中的“Worker Pool”。我尝试根据视频中的思路实现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视频中一样。但是控制台上没有任何输出。我尝试调试通道,发现worker函数从ports通道接收到了端口号,但似乎没有将任何内容发送到results通道中。
英文:
I was trying to build a simple TCP port scanner to practice learning concurrency in Go. I was following this youtube video(https://www.youtube.com/watch?v=LvgVSSpwND8) guide on implementing a "Worker Pool" in Go using channels and Goroutines. I tried utilising the idea from the video and I implemented TCP Scanner function as follows:
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)
}
I expected it to slowly print out the results in a random order, just like in the youtube video. But nothing was being output on the console. I tried debugging the channels and the worker functions were receiving port numbers from the ports channel, but it seems nothing is going back to the results channel.
答案1
得分: 2
这是因为你没有在应该监听结果时进行监听。
写入ports
的for循环会在第一次请求后阻塞,因为这是该通道的大小,所有的goroutine都会阻塞等待写入results
通道,因为没有goroutine在从中读取。
你可以通过在单独的goroutine中进行监听来修复它:
done := make(chan struct{})
go func() {
defer close(done)
for k := 1; k <= 65535; k++ {
fmt.Println(<-results)
}
close(results)
}()
for j := 1; j <= 65535; j++ {
ports <- j
}
close(ports)
<-done // 等待读取器完成
英文:
This is because you are not listening to the results when you should.
The for-loop that writes to ports
will block after the first 100 requests, because that is the size of that channel, and all the goroutines will block waiting to write to the results
channel, because no goroutine is reading from it.
You can fix it by listening in a separate goroutine:
done:=make(chan struct{})
go func() {
defer close(done)
for k := 1; k <= 65535; k++ {
fmt.Println(<-results)
}
close(results)
}()
for j := 1; j <= 65535; j++ {
ports <- j
}
close(ports)
<-done // Wait for the reader to finish
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论