简体   繁体   English

如何在转到 IP 地址中绑定 http.Client

[英]How to bind an http.Client in Go to an IP Address

I have a client machine with multiple NICs, how do I bind an http.Client in Go to a certain NIC or to a certain SRC IP Address?我有一台带有多个 NIC 的客户端机器,如何将 Go 中的 http.Client 绑定到某个 NIC 或某个 SRC IP 地址?

Say you have some very basic http client code that looks like:假设您有一些非常基本的 http 客户端代码,如下所示:

package main

import (
    "net/http"
)

func main() {
    webclient := &http.Client{}
    req, _ := http.NewRequest("GET", "http://www.google.com", nil)
    httpResponse, _ := webclient.Do(req)
    defer httpResponse.Body.Close()
}

Is there a way to bind to a certain NIC or IP?有没有办法绑定到某个网卡或IP?

Similar to this question , you need to set the http.Client.Transport field.此问题类似,您需要设置http.Client.Transport字段。 Setting it to an instance of net.Transport allows you to specify which net.Dialer you want to use.将其设置为net.Transport的实例允许您指定要使用的net.Dialer net.Dialer then allows you to specify the local address to make connections from. net.Dialer然后允许您指定本地地址以建立连接。

Example:例子:

localAddr, err := net.ResolveIPAddr("ip", "<my local address>")
if err != nil {
  panic(err)
}

// You also need to do this to make it work and not give you a 
// "mismatched local address type ip"
// This will make the ResolveIPAddr a TCPAddr without needing to 
// say what SRC port number to use.
localTCPAddr := net.TCPAddr{
    IP: localAddr.IP,
}


webclient := &http.Client{
    Transport: &http.Transport{
        Proxy: http.ProxyFromEnvironment,
        DialContext: (&net.Dialer{
            LocalAddr: &localTCPAddr,
            Timeout:   30 * time.Second,
            KeepAlive: 30 * time.Second,
            DualStack: true,
        }).DialContext,
        MaxIdleConns:          100,
        IdleConnTimeout:       90 * time.Second,
        TLSHandshakeTimeout:   10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    },
}

Here is a fully working example that incorporates the answer from Tim.这是一个完整的示例,其中包含了 Tim 的答案。 I also broke out all of the nested pieces to make it easier to read and learn from.我还打破了所有嵌套的部分,以便于阅读和学习。

package main

import (
    "fmt"
    "io/ioutil"
    "net"
    "net/http"
    "time"
)

func main() {
    localAddr, err := net.ResolveIPAddr("ip", "10.128.64.219")
    if err != nil {
        panic(err)
    }

    localTCPAddr := net.TCPAddr{
        IP: localAddr.IP,
    }

    d := net.Dialer{
        LocalAddr: &localTCPAddr,
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
    }

    tr := &http.Transport{
        Proxy:               http.ProxyFromEnvironment,
        Dial:                d.Dial,
        TLSHandshakeTimeout: 10 * time.Second,
    }

    webclient := &http.Client{Transport: tr}

    // Use NewRequest so we can change the UserAgent string in the header
    req, err := http.NewRequest("GET", "http://www.google.com:80", nil)
    if err != nil {
        panic(err)
    }

    res, err := webclient.Do(req)
    if err != nil {
        panic(err)
    }

    fmt.Println("DEBUG", res)
    defer res.Body.Close()

    content, err := ioutil.ReadAll(res.Body)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s", string(content))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM