我在主機上有幾個IP,並且想要從HttpClient
與HttpRequestMessage
建立連接時選擇使用哪一個IP。如果沒有我自己去插座並自己編寫一個簡單的http客戶端,這可以做到嗎?HttpRequestMessage在多IP環境中配置IP
我在找的相當於connect
的socket
的等級,但是對於HttpClient
......或其他選擇。
我在主機上有幾個IP,並且想要從HttpClient
與HttpRequestMessage
建立連接時選擇使用哪一個IP。如果沒有我自己去插座並自己編寫一個簡單的http客戶端,這可以做到嗎?HttpRequestMessage在多IP環境中配置IP
我在找的相當於connect
的socket
的等級,但是對於HttpClient
......或其他選擇。
所以,如果你使用的是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。
我會碰到一個域。我只需要它看到不同的IP地址。有沒有辦法避免提到一個URI? – CodeAngry
@CodeAngry我寫了一個委託處理程序,應該盡你所需。 – spender
@CodeAngry我對代碼進行了更改以避免併發問題。 – spender