一個理論:
HttpWebRequest的依賴於一個潛在的ServicePoint。 ServicePoint表示到URL的實際連接。與瀏覽器保持與請求之間打開的URL的連接方式大致相同,並重新使用該連接(以消除打開和關閉每個請求的連接開銷),ServicePoint爲HttpWebRequest執行相同的功能。
我認爲您爲ServicePoint設置的BindIPEndPointDelegate並未在每次使用HttpWebRequest時調用,因爲ServicePoint正在重新使用連接。如果您可以強制連接關閉,那麼對該URL的下一次調用應該會導致ServicePoint需要再次調用BindIPEndPointDelegate。
不幸的是,ServicePoint接口看起來並不能讓您直接強制關閉連接。
兩種溶液(每個具有略微不同的結果)
1)對於每個請求,設置HttpWebRequest.KeepAlive =假。在我的測試中,這導致綁定委託與每個請求一對一調用。
2)將ServicePoint ConnectionLeaseTimeout屬性設置爲零或某個小值。這將會週期性地強制調用綁定代理(不是每個請求都是一對一的)。
從documentation:
您可以使用此屬性來確保的ServicePoint對象的 活動連接不會無限期地保持打開。此屬性爲 ,適用於應該刪除連接的場景以及定期重新建立 的場景,例如負載平衡場景。
默認情況下,當請求的KeepAlive爲true時,由於 處於非活動狀態,因此MaxIdleTime 屬性會設置關閉ServicePoint連接的超時時間。如果ServicePoint具有活動連接,則MaxIdleTime 不起作用,並且連接將無限期地保持打開狀態。
當ConnectionLeaseTimeout屬性被設定爲比 -1以外的值,並經過指定的時間之後,活性的ServicePoint連接正在服務通過設置的KeepAlive到 在該請求假的請求後關閉。
設置此值會影響由ServicePoint對象管理的所有連接。
public class UseIP
{
public string IP { get; private set; }
public UseIP(string IP)
{
this.IP = IP;
}
public HttpWebRequest CreateWebRequest(Uri uri)
{
ServicePoint servicePoint = ServicePointManager.FindServicePoint(uri);
servicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
{
IPAddress address = IPAddress.Parse(this.IP);
return new IPEndPoint(address, 0);
};
//Will cause bind to be called periodically
servicePoint.ConnectionLeaseTimeout = 0;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
//will cause bind to be called for each request (as long as the consumer of the request doesn't set it back to true!
req.KeepAlive = false;
return req;
}
}
以下(鹼性)測試在Bind委託結果獲取調用爲每個請求:
static void Main(string[] args)
{
//Note, I don't have a multihomed machine, so I'm not using the IP in my test implementation. The bind delegate increments a counter and returns IPAddress.Any.
UseIP ip = new UseIP("111.111.111.111");
for (int i = 0; i < 100; ++i)
{
HttpWebRequest req = ip.CreateWebRequest(new Uri("http://www.yahoo.com"));
using (WebResponse response = req.GetResponse())
{
}
}
Console.WriteLine(string.Format("Req: {0}", UseIP.RequestCount));
Console.WriteLine(string.Format("Bind: {0}", UseIP.BindCount));
}
是的,我想快速更改我的IP地址。我應該走什麼路? – Xaqron 2011-05-24 18:05:26
你有沒有例外? – alexD 2011-05-24 18:18:55
您可以嘗試僅在第一次進行綁定並將其保存在靜態變量或實例變量中? – Cilvic 2011-05-24 18:22:06