HttpWebRequest的并发限制

我正在编写一个应用程序来衡量我使用C#下载网页的速度。 我提供了一个唯一域名列表,然后我生成X个线程并执行HTTPWebRequests,直到消耗了域列表。 问题是无论我使用多少线程,我每秒只能获得大约3页。

我发现System.Net.ServicePointManager.DefaultConnectionLimit是2,但我的印象是这与每个域的连接数有关。 由于列表中的每个域都是唯一的,因此这不应成为问题。

然后我发现GetResponse()方法阻止来自所有其他进程的访问,直到关闭WebResponse: http : //www.codeproject.com/KB/IP/Crawler.aspx#WebRequest ,我还没有找到任何其他信息。 web支持这个声明,但是我使用套接字实现了一个HTTP请求,我注意到了一个显着的加速(4x到6x)。

所以我的问题是:有没有人确切知道HttpWebRequest对象是如何工作的?除了上面提到的内容之外是否有解决方法?或者是否有任何用C#编写的高速网络爬虫的例子?

您是否尝试过使用诸如BeginGetResponse()之类的异步方法?

如果您使用的是.net 4.0,则可能需要尝试此代码。 基本上我使用Tasks在特定站点上发出1000个请求(我使用它在我的开发机器上对应用程序进行负载测试,我看到没有限制,因为我的应用程序快速连续看到这些请求)

public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 1000; i++) { var webRequest = WebRequest.Create(textBox1.Text); webRequest.GetReponseAsync().ContinueWith(t => { if (t.Exception == null) { using (var sr = new StreamReader(t.Result.GetResponseStream())) { string str = sr.ReadToEnd(); } } else System.Diagnostics.Debug.WriteLine(t.Exception.InnerException.Message); }); } } } public static class WebRequestExtensions { public static Task GetReponseAsync(this WebRequest request) { return Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); } } 

由于这里的工作负载是I / O限制的,因此不需要产生线程来完成工作,实际上可能会损害性能。 使用WebClient类上的Async方法使用I / O完成端口,因此性能更高,资源更少。

您应该使用BeginGetResponse方法,该方法不会阻塞并且是异步的。

当处理I / O绑定异步时,仅仅因为您生成一个线程来执行I / O工作,该线程仍然会被阻塞,等待硬件(在这种情况下是网卡)响应。 如果你使用内置的BeginGetResponse,那么该线程只会在网卡上排队,然后可以做更多的工作。 硬件完成后,它会通知您,此时将调用您的回调。

我想说明BeginGetResponse方法并非完全异步:(来自MSDN )

在此方法变为异步之前, BeginGetResponse方法需要完成一些同步设置任务(例如,DNS解析,代理检测和TCP套接字连接)。 因此,永远不应在用户界面(UI)线程上调用此方法,因为它可能需要一些时间,通常为几秒钟。