使用无缓冲通道的并发问题
Concurrency Problems using unbuffered channel
我在 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
频道范围内:
for word := range words {
preparedSubdomain := word + "." + domain
// ...
}
一旦接收到通道上发送的所有值(在通道关闭之前发送),通道上的 for ... range
就会终止。请注意,简单的 receive operator will not terminate nor panic if the channel is closed, instead it will yield the zero value of the channel's element type. So your original loop would never terminate. Spec: Receive operator:
A receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received.
其次,在 CheckWildcardSubdomain()
内部,state.FinalResults
字段被同时读取/修改,没有同步。这是未定义的行为。
您必须同步对此字段的访问,例如使用互斥锁,或者您应该找到其他方式来交流和收集结果,例如使用频道。
查看此相关问题,了解一种优雅、高效且可扩展的方法:
我在 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
频道范围内:
for word := range words {
preparedSubdomain := word + "." + domain
// ...
}
一旦接收到通道上发送的所有值(在通道关闭之前发送),通道上的 for ... range
就会终止。请注意,简单的 receive operator will not terminate nor panic if the channel is closed, instead it will yield the zero value of the channel's element type. So your original loop would never terminate. Spec: Receive operator:
A receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received.
其次,在 CheckWildcardSubdomain()
内部,state.FinalResults
字段被同时读取/修改,没有同步。这是未定义的行为。
您必须同步对此字段的访问,例如使用互斥锁,或者您应该找到其他方式来交流和收集结果,例如使用频道。
查看此相关问题,了解一种优雅、高效且可扩展的方法: