TCP套接字中出现SocketError.ConnectionReset的可能原因是什么?

3
我有一个基于TCP套接字的客户端服务器系统。在客户端断开网络连接并重新连接时,我会自动收到来自客户端的SocketError.ConnectionReset命令,并根据此命令在服务器端关闭套接字。这也没问题。
但是,当我查看客户端时,它显示套接字仍与服务器连接着(关于“套接字仍与服务器连接”[不是每次发生],有时显示已断开连接,有时显示已连接)。
引用:
“服务器从客户端端获得了一个SocketError.ConnectionReset,但客户端仍然连接,这有意义吗?”
因此,我想知道SocketError.ConnectionReset可能的原因以及如何处理我提到的这种问题?
再次声明,在正常环境下一切都正常运行(例如,如果我退出客户端,则会断开套接字,服务器同样)
提前致谢。
编辑:
以下是客户端代码。实际上,这是一个定时器,它在程序生命周期内每3秒钟Tick一次,并检查套接字是否已连接,如果已断开连接,则尝试通过新的套接字实例重新连接。
private void timerSocket_Tick(object sender, EventArgs e)
        {
            try
            {
                if (sck == null || !sck.Connected)
                {
                    ConnectToServer();
                }
            }
            catch (Exception ex)
            {
                RPLog.WriteDebugLog("Exception occcured at: "+ System.Reflection.MethodBase.GetCurrentMethod().ToString()+"Message: "+ex.Message);
            }
        }

在正常情况下(没有网络断开/重新连接),如果TCP服务器从任何客户端获得SocketError.ConnectionReset,则在客户端侧,我会看到客户端套接字已断开,并尝试通过所示代码重新连接它。但是当早期发生的情况发生时,服务器收到SocketError.ConnectionReset,但客户端仍显示它仍然连接着。尽管TCP服务器显示重置命令来自确切的客户端侧。

4个回答

1
您使用Socket.Connected的问题在于它只能告诉您最后一次发送或接收操作时的连接状态。也就是说,除非您首先尝试向其发送数据或从其接收数据,否则它不会告诉您套接字已断开连接。
来自Socket.Connected属性的MSDN描述
获取一个值,该值指示Socket是否连接到远程主机,截至最后一次发送或接收操作。
因此,在您的示例中,如果套接字在您上次发送或接收任何数据时正常工作,则timerSocket_Tick()方法永远不会调用ConnectToServer(),即使套接字现在未连接。

1

有几种原因,但最常见的是您向已经关闭连接的另一端写入了数据。换句话说,这是应用程序协议错误。当它发生时,您别无选择,只能关闭套接字,它已经失效了。但是您可以修复潜在的原因。


1
当讨论类似TCP/IP问题时,必须提及客户端和服务器之间的网络细节。
当一方表示连接被重置时,这仅意味着在线路上出现了一个RST数据包。但要知道是谁发送了RST数据包以及原因,您必须使用网络数据包捕获工具(如Wireshark和其他类似工具)。

https://en.wikipedia.org/wiki/Transmission_Control_Protocol

你不会轻易地在.NET Framework级别找到原因。

当一方出现“对等方重置连接”错误时,这意味着对等方已发送了一个RST数据包。本地也可能因为本地原因而给出“连接重置”,例如未能获取传输的任何ACK,此时除了这些传输之外,在线路上什么也不会出现。在任何情况下,FIN都与此无关。-1 - user207421

0
如何处理我所提到的这种问题?
关闭套接字并初始化一个新的连接。

当我重新启动客户端时,它会创建一个新的连接并正常工作。但我想知道背后的原因。另外,我不想重新启动客户端应用程序。在成功断开连接后,没有重新初始化连接的方法。请参见编辑。 - Rezoan
@Rezoan,CodeCaster是正确的。这些天你不能指望连接始终保持连接。你的应用程序需要在连接丢失时能够重新连接,并能够应对从几秒钟到数天的网络中断期间。你不能仅仅假设连接将一直存在-你需要计划当你失去连接时该做什么,而不是假设你不会失去连接。 - Ben
@Ben,我并不是说CodeCaster错了。我知道我必须重新初始化连接。但是在这种情况下,当服务器从任何对等方收到SocketError.ConnectionReset时,如果对等方不自行重置套接字连接,我们无法发送进一步的命令来强制对等方重置套接字连接。我想知道如何在这种情况下重置它的解决方案?你可以看到编辑。 - Rezoan
1
请解释您正在尝试做什么。在连接重置后,您无法通过套接字发送或接收任何内容。您无法强制断开连接的客户端从服务器重新连接,您的客户端应该自行检测并启动重新连接。一旦您尝试通过已断开的连接发送任何内容,该连接就会出现故障。 - CodeCaster
@CodeCaster,确切地说,客户端应该自己检测并启动,但有时客户端在这种情况下没有断开连接。我已经再次编辑了问题,您可以看到。 - Rezoan
2
@Rezoan,客户端知道连接是否重置有什么关系吗?你需要先回答这个问题。答案将指导您采取适当的行动 - 可能是在应用程序中使用某种“心跳”消息。请参阅此答案以获取更多信息:http://stackoverflow.com/questions/5338352/asyncsockets-and-silent-disconnections/5338459#5338459 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接