c# - .NET 没有可靠的异步套接字通信吗?

标签 c# .net sockets stream web-crawler

我曾经用 .NET 写过一个 Crawler。为了提高其可扩展性,我尝试利用.NET 的异步API。

System.Net.HttpWebRequest 具有异步 API BeginGetResponse/EndGetResponse。然而,这对 API 只是为了获取一个 HTTP 响应 header 和一个 Stream 实例,我们可以从中提取 HTTP 响应内容。因此,我的策略是使用 BeginGetResponse/EndGetResponse 异步获取响应流,然后使用 BeginRead/EndRead 从响应流实例异步获取字节。

在爬虫进行压力测试之前,一切似乎都很完美。压力测试下,爬虫内存占用过高。我用 WinDbg+SoS 检查了内存,发现很多字节数组被 System.Threading.OverlappedData 实例占用。在互联网上搜索后,我找到了这个知识库文章 http://support.microsoft.com/kb/947862来自微软。

根据 KB,异步 I/O 的数量应该有一个“上限”,但它没有给出一个“建议的”界限值。因此,在我看来,此知识库文章毫无帮助。这显然是一个 .NET 错误。最后,我不得不放弃从响应流中异步提取字节的想法,而只是以同步方式进行。

The .NET library that allows Asynchronous IO with dot net sockets (Socket.BeginSend / Socket.BeginReceive / NetworkStream.BeginRead / NetworkStream.BeginWrite) must have an upper bound on the amount of buffers outstanding (either send or receive) with their asynchronous IO.

The network application should have an upper bound on the number of outstanding asynchronous IO that it posts.

编辑:添加一些问号。

有人有在 Socket 和 NetworkStream 上进行异步 I/O 的经验吗? 一般而言,生产中的爬虫是通过同步还是异步方式与互联网进行 I/O?

最佳答案

嗯,这不是 .NET 框架的问题。链接的知识库文章可能会更明确一些:“你正在使用一把上膛的枪,当你将它瞄准你的脚时会发生这种情况”。那把枪中的子弹是 .NET,它使您能够启动尽可能多的异步 I/O 请求。它会做你要求它做的事,直到你达到某种资源限制。在这种情况下,第 0 代堆中的固定接收缓冲区可能过多。

资源管理在很大程度上仍然是我们的工作,而不是 .NET 的工作。这与无限制地分配内存没有什么不同。解决这个特殊问题需要您限制未完成的 BeginGetResponse() 请求的数量。拥有数百个毫无意义,每个人都必须一次一个地挤过 Intertube。添加另一个请求只会导致它需要更长的时间才能完成。或者让你的程序崩溃。

关于c# - .NET 没有可靠的异步套接字通信吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/236171/

相关文章:

c# - Windows Phone 键盘打开事件和属性

c# - 使用 List<string> 替换字符串

Java 客户端 SSLSocket : How to tell if remote end has closed the connection?

c++ - Linux内核实现

c# - 在桌面上创建快捷方式

c# - 在使用 Unity 配置依赖注入(inject)时,如何防止 EF Code First 尝试在我的数据库上运行迁移?

c# - 如何在 .NET 中释放 COM 句柄

c# - 如何使用 IEnumerable 实现进度?

java - Android蓝牙发送文件问题

c# - 在使用 EF6 和 MVC 5 进行代码优先迁移期间,导航属性不是类型的声明属性