我正在尝试用Go编写一个微型应用程序,该应用程序可以将HTTP请求发送到所有IP地址,以期找到特定的内容。问题是当异步执行调用时,应用程序似乎以一种非常特殊的方式崩溃。
ip / validator.go
package ip
import (
"io/ioutil"
"net/http"
"regexp"
"time"
)
type ipValidator struct {
httpClient http.Client
path string
exp *regexp.Regexp
confirmationChannel *chan string
}
func (this *ipValidator) validateUrl(url string) bool {
response, err := this.httpClient.Get(url)
if err != nil {
return false
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return false
}
bodyBytes, _ := ioutil.ReadAll(response.Body)
result := this.exp.Match(bodyBytes)
if result && this.confirmationChannel != nil {
*this.confirmationChannel <- url
}
return result
}
func (this *ipValidator) ValidateIp(addr ip) bool {
httpResult := this.validateUrl("http://" + addr.ToString() + this.path)
httpsResult := this.validateUrl("https://" + addr.ToString() + this.path)
return httpResult || httpsResult
}
func (this *ipValidator) GetSuccessChannel() *chan string {
return this.confirmationChannel
}
func NewIpValidadtor(path string, exp *regexp.Regexp) ipValidator {
return newValidator(path, exp, nil)
}
func NewAsyncIpValidator(path string, exp *regexp.Regexp) ipValidator {
c := make(chan string)
return newValidator(path, exp, &c)
}
func newValidator(path string, exp *regexp.Regexp, c *chan string) ipValidator {
httpClient := http.Client{
Timeout: time.Second * 2,
}
return ipValidator{httpClient, path, exp, c}
}
main.go
package main
import (
"./ip"
"fmt"
"os"
"regexp"
)
func processOutput(c *chan string) {
for true {
url := <- *c
fmt.Println(url)
}
}
func main() {
args := os.Args[1:]
fmt.Printf("path: %s regex: %s", args[0], args[1])
regexp, regexpError := regexp.Compile(args[1])
if regexpError != nil {
fmt.Println("The provided regexp is not valid")
return
}
currentIp, _ := ip.NewIp("172.217.22.174")
validator := ip.NewAsyncIpValidator(args[0], regexp)
successChannel := validator.GetSuccessChannel()
go processOutput(successChannel)
for currentIp.HasMore() {
go validator.ValidateIp(currentIp)
currentIp = currentIp.Increment()
}
}
请注意main.go中的行go validator.ValidateIp(currentIp)
。如果我删除单词“ go”以执行主例程中的所有内容,代码将按预期工作->它将请求发送到以172.217.22.174开头的IP地址,并且其中一个应返回与ipValidator匹配的正则表达式相匹配的合法结果初始化时,URL被传递到通道,并由main.go中的processOutput
函数打印出该值。问题在于,仅在go
前面添加validator.ValidateIp(currentIp)
会破坏该功能。实际上,根据调试器的说法,我似乎从未走过Validator.go中response, err := this.httpClient.Get(url)
的内容。
斗争是真实的。如果我决定扫描整个Internet,则需要经过256 ^ 4个IP地址。除非我找到一种将流程拆分为多个例程的方法,否则将需要数年时间。