关于.NET(C#)里使用HttpWebRequest中碰到的一些和Keep-Alive相关的内容
c#采集其他网站数据时,会比较多的使用HttpWebRequest来实现HTTP访问,读取网站内容。
最近关注一下几个问题:
- HttpWebRequest.ServicePoint
- ServicePointManager
- request.KeepAlive
- ServicePoint.SetTcpKeepAlive
- ServicePoint.ConnectionLimit
- ServicePoint.MaxIdleTime
- ServicePointManager.MaxServicePointIdleTime
- ServicePoint.ConnectionLeaseTimeout
一、ServicePoint:
每个请求背后都有一个ServicePoint,可以把ServicePoint想象成请求背后的TCP连接对象,通过设置ServicePoint的相关属性,可以控制TCP连接的一些行为。
二、ServicePointManager
顾名思义,这个是对 ServicePoint 进行管理的类,设置ServicePointManager的一些属性,就可以控制ServicePoint默认的一些属性,比如下面出现的Tcp KeepAlive,Connection Limit等等。
三、request.KeepAlive
request.KeepAlive这个bool类型KeepAlive,是对Http请求的KeepAlive的控制,不是对TCP的KeepAlive。可以参考:
HTTP协议Keep-Alive模式详解和HTTP头字段总结
四、ServicePoint.SetTcpKeepAlive
ServicePoint的SetTcpKeepAlive是设置TCP连接的KeepAlive特性,三个参数SetTcpKeepAlive(bool enabled, int keepAliveTime, int keepAliveInterval)的意思分别是:是否启用TCP的KeepAlive。关于TCP的Keep-Alive可以参考这个文章:UNIX网络编程——socket的keep-alive
五、ConnectionLimit
ServicePoint.ConnectionLimit和ServicePointManager.DefaultConnectionLimit都可以设置对某个URI资源可以同时访问的最大数量。HTTP协议规范里说,一个用户最多可以同时建立两个HTTP连接,如果大量线程同时请求一个站点,可能会受到限制。ConnectionLimit在Windows 10、Windows Server 2008 R2、Windows7 里默认限制是2。修过修改ConnectionLimit应该可以允许更多的请求同时进行。
六、MaxIdleTime
附1:
.NET的 HttpWebRequest 设置KeepAlive时,有一个问题,就是只有第一次发送出去的请求是带有KeepAlive标头的,后续的请求没有KeepAlive标头,解决这个问题的方式,是使用反射。
例如:
1 //.Net Framework 存在设置 HTTP Keep-Alive的BUG,每域名只有第一次请求Keep-Alive标头存在,后续请求需要靠此代码修正 2 var sp = request.ServicePoint; 3 var prop = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic); 4 prop.SetValue(sp, (byte)0, null);
这样设置之后,每次请求都可以发送KeepAlive标头。