绑定一个IP地址只适用于第一次 [英] Binding an IP address just works for the first time

查看:206
本文介绍了绑定一个IP地址只适用于第一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从可用的服务器上的IP地址来拨打网络请求,所以我使用这个类:

I want to make a web request from one of available IP addresses on server so I use this class:

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 = new BindIPEndPoint(Bind);
        return WebRequest.Create(uri) as HttpWebRequest;
    }

    private IPEndPoint Bind(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
    {
        IPAddress address = IPAddress.Parse(this.IP);
        return new IPEndPoint(address, 0);
    }
}

然后:

UseIP useIP = new UseIP("Valid IP address here...");
Uri uri = new Uri("http://ip.nefsc.noaa.gov");
HttpWebRequest request = useIP.CreateWebRequest(uri);
// Then make the request with the specified IP address

但解决的只是工作的第一次!

But the solution just works the first time!

推荐答案

一个理论:

HttpWebRequest的依赖于底层的ServicePoint。再$ P $的的ServicePoint psents到URL的实际连接。大部分在浏览器中保持请求之间打开一个URL连接和重用那些连接(以消除开放的开销和关闭与每个请求的连接)同样的方式,执行的ServicePoint为HttpWebRequest的相同的功能。

HttpWebRequest relies on an underlying ServicePoint. The ServicePoint represents the actual connection to the URL. Much in the same way your browser keeps a connection to a URL open between requests and reuses that connection (to eliminate the overhead of opening and closing the connection with each request), ServicePoint performs the same function for HttpWebRequest.

我认为要设置为的ServicePoint的BindIPEndPointDelegate没有被要求每次使用HttpWebRequest的,因为是的ServicePoint重用连接。如果你可以强制连接关闭,则对该URL下一次调用应导致的ServicePoint需要再次调用BindIPEndPointDelegate。

I think that the BindIPEndPointDelegate that you are setting for the ServicePoint is not being called on each use of HttpWebRequest because the ServicePoint is reusing the connection. If you could force the connection to close, then the next call to that URL should cause the ServicePoint to need to call BindIPEndPointDelegate again.

不幸的是,它不会出现该接口的ServicePoint让你直接强制连接关闭的能力。

Unfortunately, it doesn't appear that the ServicePoint interface gives you the ability to directly force a connection to close.

两种解决方案(每个稍有不同的结果)

Two solutions (each with slightly different results)

1)对于每个请求,设置HttpWebRequest.KeepAlive =假。在我的测试中,这引起了绑定委托被调用一换一与每个请求。

1) For each request, set HttpWebRequest.KeepAlive = false. In my test, this caused the Bind delegate to get called one-for-one with each request.

2)设置的ServicePoint ConnectionLeaseTimeout属性设置为零或一些小的值。这将有周期性强制绑定委托效应被称为(不是一换一的每个请求)。

2) Set the ServicePoint ConnectionLeaseTimeout property to zero or some small value. This will have the effect of periodically forcing the Bind delegate to be called (not one-for-one with each request).

文档

您可以使用此属性来确保的ServicePoint对象
  活动连接不会继续开放下去。此属性
  用于场景中的连接应被丢弃和
  定期重建,如负载平衡方案。

You can use this property to ensure that a ServicePoint object's active connections do not remain open indefinitely. This property is intended for scenarios where connections should be dropped and reestablished periodically, such as load balancing scenarios.

在默认情况下,当是的KeepAlive如此的要求,MaxIdleTime
  属性设置超时关闭,由于连接的ServicePoint
  不活动。如果拥有的ServicePoint活动连接,MaxIdleTime
  有没有影响,连接无限期地保持打开。

By default, when KeepAlive is true for a request, the MaxIdleTime property sets the time-out for closing ServicePoint connections due to inactivity. If the ServicePoint has active connections, MaxIdleTime has no effect and the connections remain open indefinitely.

当的ConnectionLeaseTimeout属性被设定为比其它的值
  -1,经过指定的时间后,有源的ServicePoint连接是通过设置的KeepAlive到服务请求后关闭
  虚假的要求。

When the ConnectionLeaseTimeout property is set to a value other than -1, and after the specified time elapses, an active ServicePoint connection is closed after servicing a request by setting KeepAlive to false in that request.

设置此值会影响通过的ServicePoint对象管理的所有连接。

Setting this value affects all connections managed by the ServicePoint object.

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;
    }
}

以下(基本)的测试中绑定的委托结果获取调用每个请求:

The following (basic) test results in the Bind delegate getting called for each request:

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地址只适用于第一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆