异步执行时,HTTP请求失败

时间:2018-09-02 12:35:43

标签: go

我正在尝试用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地址。除非我找到一种将流程拆分为多个例程的方法,否则将需要数年时间。

0 个答案:

没有答案