当前位置: 代码迷 >> C# >> 关于C# TCP断线重连的有关问题 百度谷歌后未能找到到满意答案 接着昨天的帖子
  详细解决方案

关于C# TCP断线重连的有关问题 百度谷歌后未能找到到满意答案 接着昨天的帖子

热度:21   发布时间:2016-05-05 03:54:54.0
关于C# TCP断线重连的问题 百度谷歌后未能找到到满意答案 接着昨天的帖子
之前问过关于SP123大神关于c# tcp同步通讯+多线程的处理方式.通讯 接收 处理数据 都成功了,http://bbs.csdn.net/topics/391025405但是有一个问题,可能会发生网络掉线或者服务器设备损坏无法发出数据的问题。这个时候可能网线恢复或者设备重新开始工作后 我需要我这边的c# sokcte客户端能够重新连接,以下是我的解决思路,但是这样 数据会发生错位的解析处理,我不知道是不是我的思路不对,还是因为i线程池造成的问题,希望耐心看完代码解答一下 谢谢各位!

 static void Main(string[] args)
        {
            StarMain();
        }

        public static void StarMain()
        {
            foreach (Address address in Common.GetAddress())
            {
                ThreadPool.QueueUserWorkItem(h => SocketClient(address.IP, address.Port));
                Thread.Sleep(10);
            }
            Console.ReadLine();
        }

        /// <summary>
        /// 程序开始
        /// </summary>
        public static void SocketClient(string host, int port)
        {
            try
            {
                ByteQueue queue = new ByteQueue();
                IPAddress ip = IPAddress.Parse(host);
                IPEndPoint ipe = new IPEndPoint(ip, port);
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Connect(ipe);
                Console.WriteLine(ip + " Connected......");
                while (true)
                {
                    //建立缓冲区
                    byte[] recByte = new byte[4096];
                    int bytes = socket.Receive(recByte, recByte.Length, 0);

                    //分多次接收
                    byte[] reallData = new byte[bytes];
                    Array.Copy(recByte, reallData, reallData.Length);
                    queue.Enqueue(reallData);

                    //while可处理同时接收到多个包 防止一帧数据不是完整的包  
                    while (queue.Find())
                    {
                        byte[] readBuffer = queue.Dequeue();

                        //解析雷达数据 包含平均速度/占有率/车流量
                        string data = BitConverter.ToString(readBuffer);

                        if (data.StartsWith("FF-FF-FF-FF-CA-CB-CC-CD") && data.EndsWith("EA-EB-EC-ED"))
                        {
                            GetData(data, host, port, DateTime.Now);
                        }
                        else if (data.StartsWith("0A 0B 0C 0D") && data.EndsWith("EA EB EC ED"))//历史数据
                        {
                            Regex regex = new Regex("0A 0B 0C 0D.{21}");
                            MatchCollection matches = regex.Matches(data, 0);
                            if (matches.Count > 0)
                            {
                                foreach (Match nextmach in matches)
                                {
                                    string history = nextmach.Value;
                                    string[] strTime = history.Split(' ');
                                    string year = strTime[0] + strTime[1];
                                    string moth = strTime[2];
                                    string day = strTime[3];
                                    string hh = strTime[4];
                                    string mm = strTime[5];
                                    string ss = strTime[6];
                                    DateTime time = Convert.ToDateTime(year + "-" + moth + "-" + day + " " + hh + ":" + mm + ":" + ss);
                                    GetData(data, host, port, time);
                                }
                            }
                        }
                        else
                        {
                            Console.WriteLine(data);
                        }
                    }
                }
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e.Message);
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e.Message);

                System.Timers.Timer t = new System.Timers.Timer(1000);   //实例化Timer类,设置间隔时间为10000毫秒;   
                t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到达时间的时候执行事件;   
                t.AutoReset = true;   //设置是执行一次(false)还是一直执行(true);   
                t.Enabled = true;     //是否执行System.Timers.Timer.Elapsed事件;  
            }
        }

        public static void theout(object source, System.Timers.ElapsedEventArgs e)
        {
            StarMain();
        }

------解决思路----------------------
引用:
Quote: 引用:



没我出场,看来就不行了!!!
可惜没时间
还有你重连不是这样写的。


把这个部份代码 抽出来,弄个一个方法 不要用 while (true) 去执行,应用异步 如果你坚持要用while true 那你上面的代码要改一下,不要再用时间去整这个。就是 int bytes = socket.Receive(recByte, recByte.Length, 0); 这个接收为0或内部出异常时,要结束while true 然后再延迟N秒进行重连。明白了么小明哥。




//建立缓冲区
                    byte[] recByte = new byte[4096];
                    int bytes = socket.Receive(recByte, recByte.Length, 0);
 
                    //分多次接收
                    byte[] reallData = new byte[bytes];
                    Array.Copy(recByte, reallData, reallData.Length);
                    queue.Enqueue(reallData);
 
                    //while可处理同时接收到多个包 防止一帧数据不是完整的包  
                    while (queue.Find())
                    {
                        byte[] readBuffer = queue.Dequeue();
 
                        //解析雷达数据 包含平均速度/占有率/车流量
                        string data = BitConverter.ToString(readBuffer);
 
                        if (data.StartsWith("FF-FF-FF-FF-CA-CB-CC-CD") && data.EndsWith("EA-EB-EC-ED"))
                        {
                            GetData(data, host, port, DateTime.Now);
                        }
                        else if (data.StartsWith("0A 0B 0C 0D") && data.EndsWith("EA EB EC ED"))//历史数据
                        {
                            Regex regex = new Regex("0A 0B 0C 0D.{21}");
                            MatchCollection matches = regex.Matches(data, 0);
                            if (matches.Count > 0)
                            {
                                foreach (Match nextmach in matches)
                                {
                                    string history = nextmach.Value;
                                    string[] strTime = history.Split(' ');
                                    string year = strTime[0] + strTime[1];
                                    string moth = strTime[2];
                                    string day = strTime[3];
                                    string hh = strTime[4];
                                    string mm = strTime[5];
                                    string ss = strTime[6];
                                    DateTime time = Convert.ToDateTime(year + "-" + moth + "-" + day + " " + hh + ":" + mm + ":" + ss);
                                    GetData(data, host, port, time);
                                }
                            }
                        }
                        else
                        {
                            Console.WriteLine(data);
                        }
                    }



异步我用过了 某些方面有局限 这种方式满足我的需求 不太懂你说的意思- -!


...你的需求与同步没有关系的。是你的代码方式的问题。
------解决思路----------------------
线程是相当宝贵的资源。我的电脑创建2000个线程就到头了。

  int bytes = socket.Receive(recByte, recByte.Length, 0);//这个地方楼上说了,要判断0的问题。
但还有一个问题就是如果突然中间某相交换机或者某个线子出问题了。会一直卡在这的。(某些时候你需要两个小时以上才会收到异)
.StartsWith("FF-FF-FF-FF-CA-CB-CC-CD") 这样的判断也奇怪了。转换为字符判断这是在考验服务器嘛。

看你的代码粘包根本没有做处理。网络不堵塞的情况下还可以,如果出现堵塞。你根本收不到你想要的数据。
用正则表达式就是另一个不考虑效率的问题了。
------解决思路----------------------
我一般另开个线程监视socket运行状态,如果状态不对,我就释放资源从新建立socket

不知道是否这个思路太过奔放
  相关解决方案