【问题标题】:Reset TCP connection if server closes/crashes mid connection如果服务器在连接中关闭/崩溃,则重置 TCP 连接
【发布时间】:2015-03-12 19:48:02
【问题描述】:

我有一个如下的 tcp 连接:

    public void ConnectToServer()
    {
        string mac = GetUID();


     while(true)
     {

        try
        {
             tcpClient = new TcpClient("xx.x.xx.xxx", xxxx);
             networkstream = new SslStream(tcpClient.GetStream());

                networkstream.AuthenticateAsClient("xx.x.xx.xxx");


                networkstream.Write(Encoding.UTF8.GetBytes("0002:" + mac + "\r\n"));
                networkstream.Flush();



                    string serverMessage = ReadMessage(networkstream);
                    Console.WriteLine("MESSAGE FROM SERVER: " + serverMessage);



            }
            catch (Exception e)
            {
                tcpClient.GetStream().Close();
                tcpClient.Close();


            }
    }
    }

这工作正常,可以向/从服务器发送接收数据。

我需要帮助的是,如果客户端启动时服务器没有运行,它会等待,然后在服务器启动后连接。但是,如果客户端和服务器都在运行并且一切正常,如果我关闭服务器,客户端将不会重新连接(因为我还没有任何东西可以处理事件)。

我在这里看到了一些建议投票等的答案。这是唯一的方法吗?我调用的 ReadMessage 方法也进入了无限循环。如果需要,我可以发布该代码。

我真的很想检测服务器何时关闭/崩溃并关闭流和 tcpclient 并尽快重新连接。

这是我的自述信息:

static string ReadMessage(SslStream sslStream)
    {

        if (sslStream.CanRead)
        {
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            string message_type = null;
            string actual_message = null;
            do
            {
                try
                {
                    Console.WriteLine("LENGTH: " + buffer.Length);
                    bytes = sslStream.Read(buffer, 0, buffer.Length);




                    Decoder decoder = Encoding.UTF8.GetDecoder();
                    char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                    decoder.GetChars(buffer, 0, bytes, chars, 0);
                    messageData.Append(chars);

                    message_type = messageData.ToString().Substring(0, 5);
                    actual_message = messageData.ToString().Substring(5);
                    if (message_type.Equals("0001:"))
                    {
                        m_Window pop = new m_Window();
                        pop.callHttpPost(null, new EventArgs());

                    }
                    if (messageData.ToString().IndexOf("\r\n") != -1)
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: " + e.Message);

                }
            } while (bytes != 0);
            return messageData.ToString();
        }
        return("CONNECTION HAS BEEN LOST");

    }

【问题讨论】:

    标签: c# tcp sslstream


    【解决方案1】:

    使用 TCP,您有 2 种服务器断开连接:

    • 服务器关闭
    • 服务器崩溃

    当服务器关闭时,您将在客户端套接字上收到 0 个字节,这是您知道对等方已关闭其套接字末端的方式,这称为半关闭。 但是如果服务器崩溃,事情会变得更加丑陋。 当这种情况再次发生时,您有多种可能性。 如果您不从客户端向服务器发送任何内容,那么您将无法发现服务器确实崩溃了。 找出服务器崩溃的唯一方法是让客户端发送一些东西或激活保持活动状态。如果你向一个不存在的服务器套接字发送一些东西,你将不得不等待相当长的时间,因为 TCP 会尝试多次,并重新传输,直到有服务器响应。当 TCP 重试几次后,它最终会退出,如果你有一个阻塞套接字,你会看到发送失败,这意味着你应该关闭你的套接字。

    实际上还有第三种可能的服务器断开连接,即重置,但这是例外使用的。我在这里假设,如果服务器正常关闭,则会在服务器端的套接字上执行正常关闭。最终会发送 FIN 而不是 RST,这是例外情况。

    现在回到你的情况,如果服务器崩溃,这是 TCP 设计固有的,因为所有这些重传超时和不断增加的延迟,你将不得不等待一段时间才能真正检测到存在问题。如果服务器正常关闭并再次启动,则情况并非如此,您通过接收 0 字节立即检测到。

    【讨论】:

    • 所以我的服务器现在是本地的,我 Ctrl+C 停止它,这会发送 0 字节吗?我仍然得到一个无限循环,我将我的 ReadMessage 方法添加到我的原始帖子中
    • 根据您在此处的描述,我会说不。 ctrl+C 不会强制它关闭套接字。
    • 我发现错误:一个现有的连接被远程主机强行关闭。我得到这个后是否可以重新连接?
    • 关闭套接字的一端,创建一个新的并尝试重新连接。如果连接失败,请关闭创建一个新的并重试,... 一旦您尝试使用 TCP 套接字连接,您将无法重试,您需要一个新的。我的意思是:socket.connect();中间代码; socket.connect() 不起作用。
    猜你喜欢
    • 2015-06-27
    • 2023-03-09
    • 1970-01-01
    • 2022-12-07
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    相关资源
    最近更新 更多