2015-11-17 2 views
3

У меня есть клиентская машина с несколькими сетевыми картами, как мне привязать http.Client в Перейти к определенной сетевой карте или к определенному IP-адресу SRC?Как связать http.Client в Перейти к IP-адресу

Скажем, у вас есть очень простой код клиента 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() 
} 

Есть ли способ, чтобы привязать к определенному NIC или IP?

+0

Некоторые сетевые адаптеры могут разговаривать с определенными VLAN, поэтому мне нужно указать, какой локальный адрес используется. Например, WGET поддерживает это с помощью флага командной строки --bind-address = ADDRESS. – jordan2175

ответ

8

Как и в случае с this question, вам необходимо установить поле http.Client.Transport. Установив его в экземпляр net.Transport, вы можете указать, какие net.Dialer вы хотите использовать. Затем net.Dialer позволяет указать локальный адрес для подключения.

Пример:

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, 
    }, 
} 
2

Вот полностью рабочий пример, который включает в себя ответ от Тима. Я также разбил все вложенные части, чтобы было легче читать и учиться.

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