using System; using System.Collections.Generic; using System.Net.Sockets; using System.Threading; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace HDL_ON.DriverLayer { public class Control_TcpClient { //声明IP,端口,和一个用来连接的Socket private string _ip; private bool run = true; private bool reconnect; //创建一个委托,用来满足其他类调用 public Action ReceiveEvent; private List heartBeatLogIdList = new List(); /// /// 心跳记录 /// public void ClearHeartBeatLog() { heartBeatLogIdList.Clear(); } public Socket _socket; private string host; private int port; private static uint _keepAliveTime = 20 * 1000; //无数据交互持续时间(ms) private static uint _keepAliveInterval = 500; //发送探测包间隔(ms) private bool isInit; //构造函数 public Control_TcpClient(string host, int port) { this.host = host; this.port = port; reconnect = false; } public void init() { if (isInit) { return; } isInit = true; connect(); readFormSocket(); reconnect2(); heartBeat(); } //连接 private void connect() { try { if (!run) { return; } MainPage.Log("TcpClient->connect", $"开始连接,IP:{host}"); _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _socket.Connect(host, port); reconnect = false; MainPage.Log("TcpClient->connect", $"连接成功,IP:{host}"); //设置KeepAlive _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); byte[] optionValue = new byte[12]; BitConverter.GetBytes(1).CopyTo(optionValue, 0); BitConverter.GetBytes(_keepAliveTime).CopyTo(optionValue, 4); BitConverter.GetBytes(_keepAliveInterval).CopyTo(optionValue, 8); _socket.IOControl(IOControlCode.KeepAliveValues, optionValue, null); } catch (Exception e) { MainPage.Log("TcpClient->connect", $"连接失败:{e.Message}"); } } //发送数据接收实现,断线重连 public int CommSend(byte[] buffer, int size) { int sendSize = 0; try { if (_socket.Connected) { sendSize = _socket.Send(buffer, size, SocketFlags.None); } } catch (Exception e) { MainPage.Log("TcpClient->CommSend", $"发送失败,Data:{System.Text.Encoding.UTF8.GetString(buffer)} Exception:{e.Message}"); //reconnect = true; } return sendSize; } private DateTime heartBeatTime; private void heartBeat() { new Thread(() => { while (run) { #if DEBUG Thread.Sleep(2000); #else Thread.Sleep(3000); #endif if (UdpSocket._BusSocket.IsRunning) { if (10 * 1000 < (DateTime.Now - heartBeatTime).TotalMilliseconds) { string msgId = Control.Ins.msg_id.ToString(); heartBeatLogIdList.Add(msgId); var sendJob = new JObject { { "id", Control.Ins.msg_id.ToString() }, { "time_stamp", Utlis.GetTimestamp() } }; var bodyString = JsonConvert.SerializeObject(sendJob); var sendBytes = Control.Ins.ConvertSendBodyData(CommunicationTopic.ct.HeartBeat, bodyString, false); CommSend(sendBytes, sendBytes.Length); heartBeatTime = DateTime.Now; } } } }) { IsBackground = true }.Start(); } //接收数据线程,使用阻塞方式接收数据 private void readFormSocket() { new Thread(() => { byte[] byteBuffer = new byte[1024 * 5]; while (run) { try { if (reconnect || !_socket.Connected) { Thread.Sleep(2000); continue; } int len = _socket.Receive(byteBuffer, SocketFlags.None); if (len == 0) { //已经断开 reconnect = true; } // 处理接收数据 var bytes = new byte[len]; Array.Copy(byteBuffer, 0, bytes, 0, bytes.Length); LinkMessageDecoder.getInstance().Decoder(bytes, (dd, dd2) => { Control.Ins.AnalysisReceiveData(dd, dd2); }); } catch (Exception e) { MainPage.Log("TcpClient->ReadFormSocket", $"Exception:{e.Message}"); reconnect = true; } } }) { IsBackground = true }.Start(); } Thread reconnectThread; private void reconnect2() { reconnectThread = new Thread(() => { while (run) { Thread.Sleep(2000); if (!run) { break; } if (reconnect) { close(); connect(); } } }); reconnectThread.IsBackground = true; reconnectThread.Start(); } /// /// 释放资源 /// public void Dispose() { run = false; close(); } /// /// 关闭 /// private void close() { try { MainPage.Log("TcpClient->Close", $"Socket 关闭,IP:{host}"); _socket.Close(); } catch { } } /** * 获取数据的开始位置 * @param arrayList 接收到的所有数据 * @return 数据位的开始索引 */ int getDataIndex(List arrayList) { var r = (byte)'\r'; var n = (byte)'\n'; for (int i = 0; i < arrayList.Count; i++) { //找出数据内容前面的两个换行 if (3 <= i && arrayList[i - 3] == r && arrayList[i - 2] == n && arrayList[i - 1] == r && arrayList[i] == n) { //剩余的数据 return i + 1; } } return -1; } } }