.Net异步套接字操作限制?

时间:2011-02-28 15:09:05

标签: .net sockets asynchronous

待处理的异步操作是否应该谨慎使用?

我有一大堆连接的TcpClients,我不期待输入,但是为了防止一个行为不端,我需要保持输入缓冲区为空。如果每个连接的客户端都有一个BeginRead(),它会无限期地保持打开状态,那有什么危害吗?当客户端最终关闭时,将调用回调,如果!asyncResult.IsCompleted,我可以退出它。

我不知道开始阅读多少字节,但我相信我可以共享一个缓冲区。输入到缓冲区限制可能只是在流中,未读。有没有更好的方法来有效地丢弃,禁止或等待流中数据的可用性?

否则我需要轮询可用的数据。

谢谢!

2 个答案:

答案 0 :(得分:3)

这取决于您正在运行的操作系统......

挂起的recv将使用一些非页面缓冲池,它将导致某些内存页面被锁定以进行I / O.

在Windows Vista之前,非页面缓冲池非常恐慌,并且它是一种机器范围的商品,如果它耗尽,可能导致设计不良的驱动程序崩溃...所以在Vista之前的操作系统上你可能会收到'ENOBUFS'错误由于缺少非分页池,从底层重叠的I / O系统。请参阅此处:http://www.lenholgate.com/blog/2009/03/excellent-article-on-non-paged-pool.html以获取有关非分页池限制的更多详细信息。

挂起的recv使用的另一个资源是一个或多个内存页面在操作未决时被锁定用于i / o。可以锁定的页面数量有限,因此,在某些情况下,您可能会从底层I / O系统获得“ENOBUFS”。

当然,这取决于您对这些限制是否会影响您的连接数量。

处理非托管代码中锁定的I / O页限制的“标准”方法是发布零字节读取,即具有实际为0字节长的缓冲区的读取。这意味着在读取挂起时没有锁定缓冲区空间,当它完成时,您只需发布正常读取或同步读取。

答案 1 :(得分:1)

不,他们不是。除了最终使用的套接字之外,异步操作使用事件 - 最轻量级的内核对象 - 和OVERLAPPED结构,即几个字的内存。我希望你在用完事件或内存之前很久就会用完套接字。

似乎没有机制等待数据而不在.NET 中读取它(底层的Win32 API允许执行此操作,请参阅WSAEventSelect),因此您必须读1个字节。在多个套接字之间共享一个大缓冲区,读取不同的偏移量可能是可取的,因为用于异步i / o的任何缓冲区必须保持固定,直到i / o完成。