如何以编程方式删除WebClient中的2个连接限制


88

那些“精细” RFC要求每个RFC客户端注意不要对每个主机使用超过2个连接...

Microsoft在WebClient中实现了这一点。我知道可以用

App.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
 <system.net> 
  <connectionManagement> 
   <add address="*" maxconnection="100" /> 
  </connectionManagement> 
 </system.net> 
</configuration> 

(位于http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/1f863f20-09f9-49a5-8eee-17a89b591007

但是,我该如何以编程方式进行呢?

根据 http://msdn.microsoft.com/zh-cn/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

“更改DefaultConnectionLimit属性对现有ServicePoint对象无效;它仅影响更改后初始化的ServicePoint对象。如果尚未直接或通过配置设置此属性的值,则该值默认为常量DefaultPersistentConnectionLimit。”

当我实例化WebClient时,我最好配置该限制,但是只要在编程开始时以编程方式删除此可悲的限制也可以。

我访问的服务器不是Internet上的常规Web服务器,而是在我的控制下和本地局域网中。我想进行API调用,但是我不使用网络服务或远程处理


15
这不是一个真正的标准。RFC“建议”将客户端限制为两个连接,但这并不是必须的。海报极有可能需要一次下载两个以上的项目。
Erik Funkenbusch,2009年

12
我在自己的服务器上访问API。我不想伤害互联网上的主机。
基督教徒

12
我增加了连接限制以构建负载测试工具。很难通过2个measley连接进行负载测试。我确信使用很多连接有很多非浏览性的原因。
ScottS

1
顺便说一句,上面的配置将影响所有.Net控制的连接,而不仅仅是Webclient。
ScottS

2
为什么要两个以上?让我们解决这个问题:为什么我不能同时异步地向服务器发出两个以上的请求?2实际上只是一个限制。
Csaba Toth 2013年

Answers:


50

通过这里和其他地方的一些技巧,我设法通过重写我使用的WebClient类来解决此问题:

class AwesomeWebClient : WebClient {
    protected override WebRequest GetWebRequest(Uri address) {
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
        req.ServicePoint.ConnectionLimit = 10;
        return (WebRequest)req;
    }
}

28
恕我直言,设置the System.Net.ServicePointManager.DefaultConnectionLimit是更好的解决方案,因为不能假设the WebRequest是a HttpWebRequest,例如,它可能是a FileRequest
丹尼斯

120

对于那些感兴趣的人:

System.Net.ServicePointManager.DefaultConnectionLimit = x (其中x是您所需的连接数)

无需额外参考

只需确保在创建服务点之前(如上文中所述)先将其称为。


那么可以将其添加到全局的application_start中吗?会影响所有建立的连接吗?
TheAlbear 2015年

如何以及在何处添加System.Net.ServicePointManager.DefaultConnectionLimit = x?
Arul Sidthan '16

奇怪的是,DefaultConnectionLimit的代码注释(使用F12导航)表示其默认值为Int32.MaxValue。但是,通过调试检查,它是2。
crokusek

7

该解决方案可让您在更改连接限制的任何时间

private static void ConfigureServicePoint(Uri uri)
{
    var servicePoint = ServicePointManager.FindServicePoint(uri);

    // Increase the number of TCP connections from the default (2)
    servicePoint.ConnectionLimit = 40;
}

第一次有人调用此FindServicePoint时,将创建一个ServicePoint实例,并创建一个WeakReference以便在ServicePointManager中保留该实例。随后对管理器的同一Uri请求将返回同一实例。如果此后未使用该连接,则GC会将其清除。


1
FindServicePoint的唯一问题是它会向您退还一个ServicePoint,但您不知道它是否会与您的客户端获得的ServicePoint相同。
jeffa00

2
这不是一个“问题”,只是工作的正常部分。与所有解决方案一样,您必须找到一种测试方法。我的方法是将.config中的设置设置为“ 1”,观察到糟糕的性能,然后在代码中进行设置(如下所示),以观察性能的提高。
算盘

1
ServicePointMaxIdleTime
Colin Breame

5

如果找到WebClient使用的ServicePoint对象,则可以更改其连接限制。HttpWebRequest对象具有一个访问器,以检索其构造要使用的访问器,因此您可以通过这种方式进行。如果幸运的话,所有请求都可能最终共享同一ServicePoint,因此您只需要执行一次即可。

我不知道更改限制的任何全球方法。如果您在执行时足够早地更改了DefaultConnectionLimit,则可能会没事。

或者,您可以忍受连接限制,因为大多数服务器软件仍然会限制您的活动。:)


该服务器不会完全限制我(实际上,它将以不同的方式),因为它完全在我的控制之下
Christian

1
服务器可能会因大量连接而节流,但即使使用小型服务器(托管在有限的VM中),我也没有遇到过这种情况。另一方面,客户端的限制2阻止了我。增加限额可以解放局势。
Csaba Toth

1
我还怀疑,任何今天的浏览器会服从2的HTTP 1.1 RFC的限制
乔鲍·托特

4

关于App.Config中的上述配置,我们有一种情况

为了使它在CONSOLE应用程序中有效,我们添加了System.Configuration参考dll。没有参考,以上内容是没有用的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.