dove2199 2018-09-02 12:35
浏览 49

异步执行时HTTP请求失败

I'm trying to write a tiny application in Go that can send an HTTP request to all IP addresses in hopes to find a specific content. The issue is that the application seems to crash in a very peculiar way when the call is executed asynchronously.

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()
    }
}

Note the line that says go validator.ValidateIp(currentIp) in main.go. Should I remove the word "go" to execute everything within the main routine, the code works as expected -> it sends requests to IP addresses starting 172.217.22.174 and should one of them return a legitimate result that matches the regexp that the ipValidator was initialized with, the URL is passed to the channel and the value is printed out by processOutput function from main.go. The issue is that simply adding go in front of validator.ValidateIp(currentIp) breaks that functionality. In fact, according to the debugger, I never seem to go past the line that says response, err := this.httpClient.Get(url) in validator.go.

The struggle is real. Should I decide to scan the whole internet, there's 256^4 IP addresses to go through. It will take years, unless I find a way to split the process into multiple routines.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 MATLAB动图的问题
    • ¥15 求差集那个函数有问题,有无佬可以解决
    • ¥15 【提问】基于Invest的水源涵养
    • ¥20 微信网友居然可以通过vx号找到我绑的手机号
    • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
    • ¥15 解riccati方程组
    • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
    • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
    • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
    • ¥50 树莓派安卓APK系统签名