using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using static AutomaticApp.Common.Sockets; using AutomaticApp.ViewModels; namespace AutomaticApp.Common { public class Clinet : SocketObject { public PushSockets pushSockets; bool IsClose = false; /// /// 当前管理对象 /// Sockets sk; /// /// 客户端 /// TcpClient client; /// /// 当前连接服务端地址 /// IPAddress Ipaddress; /// /// 当前连接服务端端口号 /// int Port; /// /// 服务端IP+端口 /// IPEndPoint ip; /// /// 发送与接收使用的流 /// NetworkStream nStream; /// /// 初始化Socket /// /// /// public override void InitSocket(IPAddress ipaddress, int port) { Ipaddress = ipaddress; Port = port; ip = new IPEndPoint(Ipaddress, Port); client = new TcpClient(); } /// /// 初始化Socket /// /// ipd地址 /// 端口 public override void InitSocket(string ipaddress, int port) { Ipaddress = IPAddress.Parse(ipaddress); Port = port; ip = new IPEndPoint(Ipaddress, Port); client = new TcpClient(); } /// /// 重写Start方法,其实就是连接服务端 /// public override void Start() { Connect(); } /// /// 连接 /// public bool Connect() { if (client != null && IsOnline() && client.Connected) return true; try { client.Connect(ip); tools.Logging("连接客户端成功,IP:" + Ipaddress + "端口号:" + Port); //将是否接收到心跳包判断位 置于false IsReturnMsg = System.DateTime.Now; //检测当前连接状态 CheckConnect(); nStream = new NetworkStream(client.Client, true); sk = new Sockets(ip, client, nStream); sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk); } catch (Exception) { tools.Logging("连接客户端失败,IP:" + Ipaddress + "端口号:" + Port); return false; } return true; } public DateTime IsReturnMsg = System.DateTime.Now; /// /// 检查链接状态 /// //private async void CheckConnect() //{ // await Task.Run(() => // { // //连接成功等待5秒后 发送心跳包 // Thread.Sleep(10000); // tools.Logging("开始发送心跳包"); // while ((System.DateTime.Now - IsReturnMsg).TotalSeconds < 150) // { // //如果没有收到心跳包 就发送一次Get // if (!IsCheckConnect) // { // //发送一次GET // SendData(new byte[] { (byte)'G', (byte)'E', (byte)'T' }); // tools.Logging("发送一次心跳包GET,上一次收到心跳包的时间差为" + (System.DateTime.Now - IsReturnMsg).TotalSeconds + "秒"); // //等待30秒钟 // Thread.Sleep(30000); // } // else //如果处于异常断开情况 则不在发送心跳包 // { // tools.Logging("目前系统由于卫通/下位机原因链接断开,停止发送心跳包GET"); // break; // } // } // tools.Logging("停止发送心跳包GET"); // //如果此时还是没有 且不是检查连接状态 // if (!IsCheckConnect) // { // //先断开链接 // Stop(); // tools.Logging("心跳包超时,主动断开链接,停止发送心跳包GET"); // //等待30秒钟 // Thread.Sleep(10000); // //初始化 // InitSocket(Ipaddress.ToString(), Port); // //重新链接 // while (!Connect()) // { // tools.Logging("心跳包超时,重新链接失败!"); // Thread.Sleep(30000); // } // tools.Logging("心跳包超时,重新链接成功!"); // } // }); //} bool IsCheckConnect = false; private async void CheckConnect() { if (IsCheckConnect) return; await Task.Run(() => { IsCheckConnect = true; //连接成功等待10秒后 发送心跳包 Thread.Sleep(10000); tools.Logging("开始发送心跳包"); while ((System.DateTime.Now - IsReturnMsg).TotalSeconds < 150) { //发送一次Get SendData(new byte[] { (byte)'G', (byte)'E', (byte)'T' }); tools.Logging("发送一次心跳包GET,上一次收到心跳包的时间差为" + (System.DateTime.Now - IsReturnMsg).TotalSeconds + "秒"); //等待30秒钟 Thread.Sleep(30000); } tools.Logging("心跳包超时,主动断开链接,停止发送心跳包GET"); //先断开链接 Stop(); //等待10秒钟 Thread.Sleep(10000); //初始化 InitSocket(Ipaddress.ToString(), Port); tools.Logging("心跳包超时,开始初始化并重新链接!"); IsCheckConnect = false; //允许重新链接并启用异步心跳包 Connect(); Thread.Sleep(10000); //重新链接 while (!IsOnline()) { tools.Logging("心跳包超时,重新链接失败!"); Connect(); Thread.Sleep(30000); } tools.Logging("心跳包超时,重新链接成功!"); }); } /// /// 读取 /// private void EndReader(IAsyncResult ir) { Sockets s = ir.AsyncState as Sockets; try { if (s != null) { if (IsClose && client == null) { sk.nStream.Close(); sk.nStream.Dispose(); return; } s.Offset = s.nStream.EndRead(ir); if (pushSockets != null) pushSockets.Invoke(s);//推送至UI if (IsOnline()) { //Thread.Sleep(100); sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk); } else { if (Ipaddress.ToString().Equals(tools.GetAppSetting("PLC_IP1"))) { MainWindow.mainViewModel.DoSocket1Connect("断开"); tools.Logging("站点1目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port); DoConnect(1); } else if (Ipaddress.ToString().Equals(tools.GetAppSetting("PLC_IP2"))) { MainWindow.mainViewModel.DoSocket2Connect("断开"); tools.Logging("站点2目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port); DoConnect(2); } } } } catch (Exception skex) { Sockets sks = s; sks.ex = skex; sks.ClientDispose = true; if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } } private bool IsDoConnect = false; /// /// 检查链接状态 /// private async void DoConnect(int id) { await Task.Run(() => { tools.Logging("站点" + id + "目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port + "开始重新连接"); IsDoConnect = true; while (!IsOnline()) { Thread.Sleep(15000); if (id == 1) MainWindow.mainViewModel.DoSocket1Connect("连接"); if (id == 2) MainWindow.mainViewModel.DoSocket2Connect("连接"); Thread.Sleep(15000); } //如果连接成功则切出检查连接模式 tools.Logging("站点" + id + "目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port + "重新链接成功,退出重新链接模式"); IsDoConnect = false; }); } /// /// 停止 /// public override void Stop() { Sockets sks = new Sockets(); try { if (client != null) { client.Client.Shutdown(SocketShutdown.Both); Thread.Sleep(10); client.Close(); IsClose = true; client = null; } else { sks.ex = new Exception("客户端没有初始化.!"); } if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } catch (Exception ex) { sks.ex = ex; } } /// /// 发送消息 /// public void SendData(byte[] SendData) { try { if (client == null || !client.Connected) { Sockets sks = new Sockets(); sks.ex = new Exception("客户端无连接.."); sks.ClientDispose = true; if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } if (client != null && client.Connected) //如果连接则发送 { if (nStream == null) { nStream = client.GetStream(); } nStream.Write(SendData, 0, SendData.Length); } } catch (Exception skex) { Sockets sks = new Sockets(); sks.ex = skex; sks.ClientDispose = true; if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } } public bool Is_Connected() { return client.Connected; } public bool IsOnline() { if (client == null) return false; return !((client.Client.Poll(1000, SelectMode.SelectRead) && (client.Client.Available == 0)) || !client.Client.Connected); } } }