首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >goroutines中的http.Client

goroutines中的http.Client
EN

Stack Overflow用户
提问于 2021-02-11 02:46:21
回答 1查看 24关注 0票数 0

我有一个包含以下内容的文本文件:

代码语言:javascript
复制
192.168.1.2$nick
192.168.1.3$peter
192.168.1.4$mike
192.168.1.5$joe

web服务器在列表中的每个IP上运行。

我需要检查服务器当前是否可用,如果不可用,则输出一条消息。

我写了一个小应用程序。它可以工作,但会周期性地产生不正确的结果--它不会为实际上不可用的服务器输出消息。

我不知道发生了什么,事实上我不确定我是否在goroutines中正确地使用了http.Client。

请帮帮我。

代码语言:javascript
复制
package main

import "fmt"
import "os"
import "strings"
import "io/ioutil"
import "net/http"
import "crypto/tls"
import "time"
import "strconv"

func makeGetRequest(URL string, c *http.Client) {
    resp, err := c.Get(URL)
    if err != nil {
        fmt.Println(err)
    }

    defer resp.Body.Close()

    if !((resp.StatusCode >= 200 && resp.StatusCode <= 209)) {
        fmt.Printf("%s-%d\n", URL, resp.StatusCode)
    }
}

func makeHeadRequestAsync(tasks chan string, done chan bool, c *http.Client) {

    for {
        URL := <-tasks

        if len(URL) == 0 {
            break
        }

        resp, err := c.Head(URL)
        if err != nil {
            fmt.Println(err)
            continue
        }
        defer resp.Body.Close() 
        if !((resp.StatusCode >= 200 && resp.StatusCode <= 209)) {
            makeGetRequest(URL, c) // !!! Some servers do not support HEAD requests. !!!
        }
    }

    done <- true
}

func main() {

    if len(os.Args) < 3 {
        fmt.Println("Usage: main <number of threads> <input-file>")
        os.Exit(0)
    }

    threadsNum, err := strconv.Atoi(os.Args[1]) 
    if err != nil {
        fmt.Println("Bad first parameter. Exit.")
        os.Exit(0)
    }

    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    client := &http.Client {
        Timeout: 30 * time.Second,
    }

    file, err := ioutil.ReadFile(os.Args[2])
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    fileLines := strings.Split(string(file), "\n") 

    tasks := make(chan string, threadsNum) 

    done := make(chan bool)

    for i := 0; i < threadsNum; i++ {
        go makeHeadRequestAsync(tasks, done, client)
    }

    for i := 0; i < len(fileLines); i++ {
        tasks <- strings.Split(string(fileLines[i]), "$")[0:1][0]
    }

    for i := 0; i < threadsNum; i++ {
        tasks <- ""
        <-done
    }
}
EN

回答 1

Stack Overflow用户

发布于 2021-06-27 01:39:46

main()函数返回时,程序终止。代码并不能确保所有goroutines都在从main返回之前完成。

通过执行以下操作进行修复:

  • 使用sync.WaitGroup等待goroutines完成后再退出程序。
  • tasks关闭时退出goroutine。提交所有工作后关闭任务。

代码如下:

代码语言:javascript
复制
func makeHeadRequestAsync(tasks chan string, wg *sync.WaitGroup, c *http.Client) {
    defer wg.Done()

    // for range on channel breaks when the channel is closed.
    for URL := range tasks {
        resp, err := c.Head(URL)
        if err != nil {
            fmt.Println(err)
            continue
        }
        defer resp.Body.Close()
        if !(resp.StatusCode >= 200 && resp.StatusCode <= 209) {
            makeGetRequest(URL, c) // !!! Some servers do not support HEAD requests. !!!
        }
    }

}

func main() {

    if len(os.Args) < 3 {
        fmt.Println("Usage: main <number of threads> <input-file>")
        os.Exit(0)
    }

    threadsNum, err := strconv.Atoi(os.Args[1])
    if err != nil {
        fmt.Println("Bad first parameter. Exit.")
        os.Exit(0)
    }

    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    client := &http.Client{
        Timeout: 30 * time.Second,
    }

    file, err := ioutil.ReadFile(os.Args[2])
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    fileLines := strings.Split(string(file), "\n")

    tasks := make(chan string)

    var wg sync.WaitGroup
    wg.Add(threadsNum)
    for i := 0; i < threadsNum; i++ {
        go makeHeadRequestAsync(tasks, &wg, client)
    }

    for i := 0; i < len(fileLines); i++ {
        tasks <- strings.Split(string(fileLines[i]), "$")[0:1][0]
    }
    close(tasks)
    wg.Wait()
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66143117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档