在主goroutine Golang中无法接收到最后一个发送到通道的值

7ajki6be  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(103)

Given TCP port scanner in golang. 2个实现,第一个是我的,第二个是从golang书。假设第二个是100%可行的测试之前,许多读者。但似乎两者都有同样的问题:在主goroutine中,results通道发送的最后一个值不能被接收,它会陷入无限等待通道的值,尽管值实际上已经发送了。一些意见:当端口数小于21时,系统工作正常;当数量大于1000时,未接收值的数量增加到大约10。我不明白为什么。
从书中实现

func worker(ports, results chan int) {
    for p := range ports {
        address := fmt.Sprintf("scanme.nmap.org:%d", p)
        conn, err := net.Dial("tcp", address)
        if err != nil {
            results <- 0
            fmt.Println("sent", p)
            continue
        }
        conn.Close()
        results <- p
        fmt.Println("sent", p)
    }
}

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

    var openports []int

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

    go func() {
        for i := 1; i <= 50; i++ {
            ports <- i
        }
    }()

    for i := 0; i < 50; i++ {
        port := <-results // after 49 it gets stuck infinitely, never proceed further
        fmt.Println("received", port, i)
        if port != 0 {
            openports = append(openports, port)
        }
    }

    close(ports)
    close(results)

    sort.Ints(openports)

    fmt.Println(openports)

}
z9smfwbn

z9smfwbn1#

通过向net.Dialer添加超时,问题已得到解决

func worker(ports, results chan int) {
    dialer := net.Dialer{Timeout: time.Second}

    for p := range ports {
        address := fmt.Sprintf("scanme.nmap.org:%d", p)
        conn, err := dialer.Dial("tcp", address)
        if err != nil {
            results <- 0
            continue
        }

        conn.Close()
        results <- p
    }
}

相关问题