C#SocketAsyncEventArgs停止触发已完成的事件

时间:2013-11-06 22:54:51

标签: c# sockets tcp asyncsocket iocp

我注意到SocketAsyncEventArgs 的.Completed事件似乎停止触发的问题。同样的SAEA可以正常启动并在池中被替换多次,但最终所有实例都将停止触发,并且因为池中替换它们的代码在事件处理程序中,所以池清空。

以下情况也显然是正确的:

1)似乎只有在服务器端套接字将数据发送到其中一个连接的客户端时才会发生。当同一个班级作为客户连接时,它似乎没有出现故障。

2)似乎在高负荷下发生。线程计数似乎一直在上升,直到最终发生错误。

3)在类似压力下的试验台似乎永远不会出现故障。 (每秒只有20条消息,测试装置已被证明为20K)

我无法粘贴相当复杂的代码,但这里是我的代码描述

1)主要灵感来自:http://vadmyst.blogspot.ch/2008/05/sample-code-for-tcp-server-using.html。它显示了如何使用事件连接完成端口,如何通过TCP连接获取不同大小的消息,等等。

2)我有一个字节缓冲区,其中所有SAEA都有一块,不重叠。

3)我有一个基于阻塞集的SAEA对象池。如果池空了太长时间,则抛出此值。

4)作为服务器,我保留从AcceptAsync函数返回的套接字集合,由客户端的端点索引。单个进程可以使用一个实例作为服务器,也可以将多个实例用作客户端(形成Web)。它们共享数据缓冲区和SAEA池。

我意识到这很难解释;我整整一天都在调试它。只是希望有人听说过这个或有有用的问题或建议。

目前,我怀疑某种程度的线程耗尽,导致SAEA无法调用完成。或者,传出缓冲区上存在某种缓冲区问题。

1 个答案:

答案 0 :(得分:1)

所以,另一天调试,最后我有一个解释。

1)SAEA没有解雇已完成的事件,因为他们无法发送更多事件。这是由Wireshark揭示的,因为TCP窗口已经清空。 (TCP ZeroWindow)

2)TCP窗口正在清空,因为网络层正在向堆栈传递一个花了太长时间才完成的事件,即网络层和UI之间没有生产者/消费者。因此,网络操作系统必须在发送ACK之前等待屏幕绘制。

3)花费太长时间的事件是GUI上的事件处理程序中的屏幕绘制。测试装备是一个控制台窗口(一个汇总传入消息的窗口),这就是为什么它不会在更高的负载下导致问题。通常不在每条消息上重绘屏幕,但这种情况正在发生,因为项目尚未完成。重绘率将在稍后修复。

4)短期解决方案只是为了确保没有图形用户界面支持节目。更强大的解决方案可能是在网络层创建生产者/消费者。