Golang工作池没有返回任何结果

huangapple go评论111阅读模式
英文:

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 &lt;-chan int, results chan&lt;- string) {
	for p := range ports {
		address := fmt.Sprintf(&quot;127.0.0.1:%d&quot;, p)
		conn, err := net.Dial(&quot;tcp&quot;, address)
		if err != nil {
			results &lt;- fmt.Sprintf(&quot;Port %d is closed: %s&quot;, p, err.Error())
		} else {
			conn.Close()
			results &lt;- fmt.Sprintf(&quot;Port %d is open&quot;, p)
		}
	}
}

func main() {
	ports := make(chan int, 100)
	results := make(chan string, 100)

	for i := 0; i &lt; cap(ports); i++ {
		go worker(ports, results)
	}

	for j := 1; j &lt;= 65535; j++ {
		ports &lt;- j
	}
	close(ports)

	for k := 1; k &lt;= 65535; k++ {
		fmt.Println(&lt;-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 &lt;= 65535; k++ {
        fmt.Println(&lt;-results)
      }
      close(results)
  }()

 for j := 1; j &lt;= 65535; j++ {
        ports &lt;- j
    }
 close(ports)
 &lt;-done  // Wait for the reader to finish

huangapple
  • 本文由 发表于 2023年7月26日 01:03:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76765006.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定