Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#SocketAsyncEventArgs和网络故障_C#_Sockets_Tcp_Asyncsocket_Iocp - Fatal编程技术网

C#SocketAsyncEventArgs和网络故障

C#SocketAsyncEventArgs和网络故障,c#,sockets,tcp,asyncsocket,iocp,C#,Sockets,Tcp,Asyncsocket,Iocp,我以规范的方式使用SAEA实现了异步套接字: 为操作准备一个SAEA池,保留引用,这样GC就不必移动内存 操作完成后,更换SAEA 我发现了一个与网络中断有关的问题。具体地说,sendAsync completion事件在发生中断时不会触发,因此我的池不会重新填充。这最终导致程序崩溃,因为不管池的大小,它都会用完SAEA 你如何避免这种情况?您不能简单地保留对旧SAEA的引用,因为这会给您一个异常,表明它已经在等待操作 我正在寻找一种方式来优雅地取代SAEA。数据无法传输不是问题。一种可能的方法

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

  • 为操作准备一个SAEA池,保留引用,这样GC就不必移动内存
  • 操作完成后,更换SAEA
  • 我发现了一个与网络中断有关的问题。具体地说,sendAsync completion事件在发生中断时不会触发,因此我的池不会重新填充。这最终导致程序崩溃,因为不管池的大小,它都会用完SAEA

    你如何避免这种情况?您不能简单地保留对旧SAEA的引用,因为这会给您一个异常,表明它已经在等待操作


    我正在寻找一种方式来优雅地取代SAEA。数据无法传输不是问题。一种可能的方法是,一旦有一定数量的对象等待,就在套接字上运行shutdown。有人有这方面的经验吗

    提议的解决方案确实有效。只需在每次发送前检查是否超出某个限制,如果超出限制,则关闭并关闭套接字。这可以防止对象泄漏,从而允许稍后进行优雅的重新连接


    我通过拔下电缆并反复重新连接来测试这一点。在旧的情况下,游泳池将是空的。现在它在网络中断中幸存了下来。

    在网络延迟基本无限的情况下(如电缆被切断时),确实可能不会发布完成消息

    从这样一个问题中恢复过来的唯一方法是实施某种令人心跳的方案。Socket上存在SO_KEEPALIVE选项,但默认行为通常不是您想要的。从MSDN:

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

    我建议你自己执行心跳计划,如果在合理的时间内没有收到响应心跳,就考虑连接“死”。例如,您可以:

  • 定期发送“心跳”(或在没有发送其他消息时)
  • 写下接收到心跳(或任何)消息的时间,并设置超时,以便在触发超时时,您已经很长时间没有收到数据,应该关闭并重新启动连接

  • 那会是什么样的中断?在大多数错误情况下,完成操作时会包含相关的错误信息。这是一个断开的电缆类型的问题吗?是的,您可以通过拔下电缆来模拟它,但可能不通过关闭网络端口来模拟。目前还有另一个海底电缆断裂,而且似乎经常发生。