2016-01-22 95 views
1

我在主機上有幾個IP,並且想要從HttpClientHttpRequestMessage建立連接時選擇使用哪一個IP。如果沒有我自己去插座並自己編寫一個簡單的http客戶端,這可以做到嗎?HttpRequestMessage在多IP環境中配置IP

我在找的相當於connectsocket的等級,但是對於HttpClient ......或其他選擇。

回答

2

所以,如果你使用的是Windows計算機上的默認HttpClient消息處理程序,HttpClient將使用.net HttpWebRequest做其工作。這又依靠ServicePointManager來提供ServicePoint來管理到URI的連接。對於任何域,您可以掛鉤到其ServicePoint以更改綁定到IPEndPoint的方式。

如果你把你正在試圖連接到並找到其ServicePoint的URI:

var sp = ServicePointManager.FindServicePoint(uri); 

那麼你可以:

var sp = ServicePointManager.FindServicePoint(new Uri("http://www.google.com")); 
sp.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) => { 
    IPAddress adapterIpAddress = //your chosen adapter's IP address 
    return new IPEndPoint(adapterIpAddress, 0); 
}; 

如果你想獲得真正的爵士,你可以摺疊這成一個DelegatingHandler,以便HttpClient爲您處理所有事情:

public class RebindingHandler : DelegatingHandler 
{ 
    private BindIPEndPoint bindHandler; 
    public RebindingHandler(IEnumerable<IPAddress> adapterAddresses, 
          HttpMessageHandler innerHandler = null) 
     : base(innerHandler ?? new WebRequestHandler()) 
    { 
     var addresses = adapterAddresses.ToList(); 
     if(!addresses.Any()) 
     { 
      throw new ArgumentException(); 
     } 
     var idx = 0; 
     bindHandler = (servicePoint, remoteEndPoint, retryCount) => { 
      int i = Interlocked.Increment(ref idx); 
      uint i2 = unchecked((uint)i); 
      int index = (int)(((long)i2) % addresses.Count); 

      IPAddress adapterIpAddress = addresses[index]; 
      return new IPEndPoint(adapterIpAddress, 0); 
     }; 
    } 

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
     CancellationToken cancellationToken) 
    { 
     var sp = ServicePointManager.FindServicePoint(request.RequestUri); 
     sp.BindIPEndPointDelegate = bindHandler; 
     var httpResponseMessage = await base.SendAsync(request, cancellationToken); 
     return httpResponseMessage; 
    } 
} 

然後,您可以:

var addresses = new List<IPAddress>(); //this contains your adapter addresses 
var client = new HttpClient(new RebindingHandler(addresses)); 

,當你使用client,內部處理程序將自動註冊相關的ServicePoint使用周圍一堆IPEndPoints的旋轉的BindIPEndPoint。

+0

我會碰到一個域。我只需要它看到不同的IP地址。有沒有辦法避免提到一個URI? – CodeAngry

+0

@CodeAngry我寫了一個委託處理程序,應該盡你所需。 – spender

+0

@CodeAngry我對代碼進行了更改以避免併發問題。 – spender