1

我注意到一个问题,即 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 无法调用完成。或者,传出缓冲区上的某种缓冲区问题。

4

1 回答 1

1

所以,又是一天的调试,最后我有一个解释。

1) SAEA 没有触发完成的事件,因为它们无法发送更多。Wireshark 发现这是由于 TCP 窗口清空所致。(TCP 零窗口)

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

3) 耗时过长的事件是 GUI 上的事件处理程序中的屏幕绘制。测试台是一个控制台窗口(一个汇总传入消息的窗口),所以这就是它在更高负载下没有引起问题的原因。在每条消息上不重绘屏幕是正常的,但发生这种情况是因为项目尚未完成。重绘率将在以后固定。

4) 短期解决方案只是确保没有图形用户界面阻碍演出。更强大的解决方案可能是在网络层创建生产者/消费者。

于 2013-11-07T18:45:59.263 回答