一个理论:
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