重置TCP连接,如果服务器关闭/崩溃连接中旬 [英] Reset TCP connection if server closes/crashes mid connection

查看:302
本文介绍了重置TCP连接,如果服务器关闭/崩溃连接中旬的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个TCP连接类似如下:

 公共无效ConnectToServer()
{
串MAC =的getuid();


,而(真)
{


{
的TcpClient =新的TcpClient(xx.x.xx .XXXXXXX);
的NetworkStream =新SslStream(tcpClient.GetStream());

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


networkstream.Write(Encoding.UTF8.GetBytes(0002+ MAC +\r\\\
));
networkstream.Flush();



串SERVERMESSAGE = ReadMessage(的NetworkStream);
Console.WriteLine(信息从服务器:+ SERVERMESSAGE);



}
赶上(例外五)
{
tcpClient.GetStream()关闭()。
tcpClient.Close();


}
}
}

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



我需要什么帮助,如果客户端启动时服务器未运行,它会等待,然后连接,一旦服务器已启动。但是,如果客户端和服务器都在运行,一切正常,如果我关闭服务器,客户端将无法重新连接(因为我没有什么要处理该事件还)。



我看到的这里的一些答案的建议和投票等。这是唯一的方法是什么?该ReadMessage方法,我称之为进入一个无限循环,以及。我可以张贴代码如果需要的话。



我真的想在服务器关闭/崩溃检测和关闭流和TcpClient的和ASAP重新连接。



下面是我的readmessage:

 静态字符串ReadMessage(SslStream sslStream )
{

如果(sslStream.CanRead)
{
字节[]缓冲区=新的字节[2048];
StringBuilder的messageData =新的StringBuilder();
INT字节= -1;
字符串message_type = NULL;
字符串actual_message = NULL;

{

{
Console.WriteLine(长:+ buffer.Length);
字节= sslStream.Read(缓冲,0,buffer.Length);




解码器解码器= Encoding.UTF8.GetDecoder();
的char [] =字符新的char [decoder.GetCharCount(缓冲,0字节)];
decoder.GetChars(缓冲液,0,字节,字符,0);
messageData.Append(字符);

message_type = messageData.ToString()子串(0,5);
actual_message = messageData.ToString()子串(5)。
如果(message_type.Equals(0001))
{
m_Window弹出=新m_Window();
pop.callHttpPost(空,新的EventArgs());

}
如果(messageData.ToString()的IndexOf(\r\\\
)= -1。!)
{
中断;
}
}
赶上(例外五)
{
Console.WriteLine(错误:+ e.Message);

}
},而(字节!= 0);
返回messageData.ToString();
}
返回(连接已丢失);

}


解决方案

通过TCP你有2种服务器断开连接的:




  • 服务器被关闭

  • 服务器崩溃



在服务器关闭时,你会收到您的客户端套接字上0字节,这是你知道对方有路关闭了的插座,其被称为半关闭的端部。
,而得到的东西,如果服务器崩溃,更难看。
当发生这种情况再次你有几种可能性。
如果不从客户端发送任何内容到服务器时,你没有办法找出该服务器确实已经坠毁。
找出服务器崩溃的唯一方法是通过让客户送东西,或通过激活存留。如果你送东西,不存在服务器套接字,你将不得不等待相当长的时间,因为TCP是要去尝试几次,直到重发有一个服务器响应。当TCP已重试几次,那么它最终会摆脱困境,如果你有一个阻塞套接字,你会看到,发送失败,这意味着你应该关闭套接字。



其实还有第三个可能的服务器断开,即复位,但是这是非常使用。我在这里假设,如果有一个gracefull服务器关闭时,执行在服务器端插座上常闭。这将在FIN最终会被发送一个RST,这是例外情况,而不是



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


I have a tcp connection like follows:

    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();


            }
    }
    }

This works fine and can send a receive data to/from the server.

What I need help with, if the server isn't running when the client starts, it'll wait and then connect once the server is up. But, if both the client and server are running and everything is working, if I close the server, the client will not reconnect(because I don't have anything to handle the event yet).

I have seen some answers on here that suggest polling and such. Is that the only way? The ReadMessage method that I call get into an infinite loop as well. I can post that code if need be.

I would really like to detect when the server closes/crashes and close the stream and the tcpclient and reconnect ASAP.

Here is my readmessage:

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");

    }

解决方案

With TCP you have 2 kinds of a server disconnect:

  • the server is closed
  • the server crashes

When the server is closed, you are going to receive 0 bytes on your client socket, this is the way you know that the peer has closed its end of the socket, which is called a half close. But thing get more ugly if the server crashes. When that happens again you have several possibilities. If you don't send anything from the client to the server, the you have not way to find out that the server has indeed crashed. The only way to find out that the server crashed is by letting the client send something or by activating keep alive. If you send something to a server socket that does not exist, you will have to wait a rather long period, because TCP is going to try several times, with retransmits untill there is a server response. When TCP has retried several times, then it will finally bail out and if you have a blocking socket you will see that the send failed, which means you should close your socket.

Actually there is a third possible server disconnect, that is a reset, but this is exceptionally used. I assume here that if there is a gracefull server shutdown, a normal close on the socket on the server end is executed. Which will end up in a FIN being sent instead of a RST, which is the exceptional case.

Now back to your situation, if the server crashes, it is inherently in the design of TCP, because of all those retransmission timeouts and increasing delays, that you will have to wait some time to actually detect that there is a problem. If the server is gracefully closed and startup again, this is not the case, this you detect immediately by receiving 0 bytes.

这篇关于重置TCP连接,如果服务器关闭/崩溃连接中旬的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆