2016-01-22 72 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