我在Go中创建了一个工具,该工具可以使用Go并发暴力破解子域。问题在于它只显示前几个结果。我的意思是,如果我指定的线程为10,则显示10,如果为100,则显示100。对此的任何解决方案。我正在关注this示例。

func CheckWildcardSubdomain(state *State, domain string, words <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()

    for {
        preparedSubdomain := <-words + "." + domain
        ipAddress, err := net.LookupHost(preparedSubdomain)

        if err == nil {
            if !state.WildcardIPs.ContainsAny(ipAddress) {
                if state.Verbose == true {
                    fmt.Printf("\n%s", preparedSubdomain)
                }

                state.FinalResults = append(state.FinalResults, preparedSubdomain)
            }
        }
    }
}

func RemoveWildcardSubdomains(state *State, subdomains []string) []string {
    var wg sync.WaitGroup
    var channel = make(chan string)

    wg.Add(state.Threads)

    for i := 0; i < state.Threads; i++ {
        go CheckWildcardSubdomain(state, state.Domain, channel, &wg)
    }

    for _, entry := range subdomains {
        sub := strings.Join(strings.Split(entry, ".")[:2][:], ".")
        channel <- sub
    }

    close(channel)
    wg.Wait()

    return state.FinalResults
}
在此先感谢您的帮助。

最佳答案

2个错误立即突出。

首先,在CheckWildcardSubdomain()中,您应该像这样在words channel 上进行设置:

for word := range words {
    preparedSubdomain := word + "." + domain
    // ...
}

一旦接收到在该 channel 上发送的所有值(在关闭 channel 之前发送),该 channel 上的for ... range将终止。请注意,如果 channel 关闭,则简单receive operator不会终止也不会出现 panic ,而是会产生 channel 元素类型的零值。因此,您的原始循环永远不会终止。 Spec: Receive operator:



其次,在CheckWildcardSubdomain()内,无需同步即可同时读取/修改state.FinalResults字段。这是未定义的行为。

您必须同步对此字段的访问,例如使用互斥锁,或者您应该找到其他沟通和收集结果的方法,例如使用 channel 。

请参阅以下相关问题,以获取一种优雅,高效且可扩展的方法:

Is this an idiomatic worker thread pool in Go?

关于go - 使用无缓冲 channel 的并发问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49875046/

10-16 07:03