C#SocketAsyncEventArgs和网络故障

时间:2014-09-03 13:34:27

标签: c# sockets tcp asyncsocket iocp

我已经使用SAEA以规范的方式实现了异步套接字:

  1. 准备好操作的SAEA池,保留引用,以便GC不必移动内存
  2. 操作完成后更换SAEA。
  3. 我发现了一个与网络中断有关的问题。具体来说,当发生中断时,sendAsync完成事件不会触发,因此我的池不会被重新填充。这最终会导致程序崩溃,因为它将耗尽SAEA,无论池的大小如何。

    你怎么避免这个?你不能简单地保留对旧SAEA的引用,因为这会给你一个例外,说它已经在等待操作了。

    我正在寻找一种优雅替换SAEA的方法。这不是数据无法传输的问题。一个可能的路由是在一定数量的对象等待后在套接字上运行shutdown。有没有人有这方面的经验?

2 个答案:

答案 0 :(得分:1)

在基本无限的网络延迟(如电缆被切断的情况下)的情况下,确实会发生没有完成的事情。

从这样的问题中恢复的唯一方法是实现某种版本的心跳方案。 SO_KEEPALIVE选项存在于套接字上,但默认行为通常不是您想要的。来自MSDN:

  

对于TCP,默认保持活动超时为2小时,保持活动时间间隔为1秒。

我建议你实施自己的心跳计划,并考虑连接"死了"如果在合理的时间内没有收到响应心跳。例如,您可以:

  1. 发送"心跳"定期(或没有其他消息发送时)
  2. 记下收到心跳(或任何)消息的时间,并设置超时,以便在超时被触发时,您没有收到数据太长时间,连接应该关闭并重新启动

答案 1 :(得分:0)

建议的解决方案确实有效。它只是在每次发送之前检查是否超出某个限制,如果是,则关闭+关闭套接字。这可以防止对象泄漏,以便以后可以正常重新连接。

我通过拔下电缆并反复重新连接来测试这一点。在旧的情况下,池将清空。现在它在网络中断后幸免于难。