using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Module.Socket.Tool { public class TcpClientChargerTool { #region 定义锁 private object lockObj = new object(); //线程同步锁 #endregion 定义锁 TcpClient ClientTcp = new TcpClient(); NetworkStream ClientStream = null; private readonly object LockHandler = new object(); /// /// 确定的已接收缓存字节数组 /// private byte[] FixedBuffer; /// /// 上次接收剩余字节 /// private List RemainBuffer = new List(); /// /// 缓存字节长度 /// private int BufferSize; /// /// 客户端是否已经连接 /// private bool IsConnected = false; private Thread DataMonitoringThread = null; private Thread ConnectMonitoringThread = null; public event EventHandler ConnectedStatusChanged; public event EventHandler DataReceived; public event EventHandler DataSended; private string _client_ip; /// /// 客户端IP地址 /// public string F_ClientIP { get { return _client_ip; } set { lock (lockObj) { _client_ip = value; } } } private int _client_port; /// /// 客户端端口号 /// public int F_ClientPort { get { return _client_port; } set { lock (lockObj) { _client_port = value; } } } /// /// 客户端任务线程是否已经开始运行 /// public bool RaskThreadIsStart { get; set; } = true; /// /// 数据接收事件是否被阻塞 /// public bool DataReceivedEventIsSuspend { get; set; } = false; /// /// 读数据超时时间(毫秒) /// public int ReadTimeout { get; set; } = 1000; public TcpClientChargerTool() { } public TcpClientChargerTool(string ipAddr, int port) { _client_ip = ipAddr; _client_port = port; } /// /// 客户端连接 /// public virtual void ClientConnect() { try { Disconnect(); ClientTcp.Connect(_client_ip, _client_port); ClientStream = ClientTcp.GetStream(); bool state = ClientTcp.Connected; if (state == false) { IsConnected = false; SetConnectStatusEvent("连接失败"); TerminateThreadsTCPStream(); } else { IsConnected = true; SetConnectStatusEvent("连接成功"); BufferSize = ClientTcp.ReceiveBufferSize; FixedBuffer = new byte[BufferSize]; RaskThreadIsStart = true; } ConnectMonitoringThread = new Thread(MonitorConnecting); ConnectMonitoringThread.Name = "TCP客户端连接状态监测" + _client_port.ToString(); ConnectMonitoringThread.Start(); DataMonitoringThread = new Thread(MonitorRecevingData); DataMonitoringThread.Name = "TCP客户端数据接收监测" + _client_port.ToString(); DataMonitoringThread.Start(); } catch (Exception ex) { SetConnectStatusEvent("连接失败" + ex.ToString()); } } /// /// 设置连接状态字符串 /// /// 连接状态字符串。比如:“连接成功” private void SetConnectStatusEvent(string status) { string strClient = ""; if (ClientTcp != null && ClientTcp.Client.LocalEndPoint != null) { strClient = ClientTcp.Client.LocalEndPoint.ToString(); } string strTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " "; string strConnectLog = strTime + "客户端" + strClient + "与服务端" + _client_ip.ToString() + ":" + _client_port.ToString() + " " + status + "!"; EventHandler ConnectedHandler; ConnectedHandler = ConnectedStatusChanged; if (ConnectedHandler != null) { ConnectedHandler.Invoke(this, new ViewLogEventArgs() { ConnectedStatus = IsConnected, IsContent = strConnectLog }); } } /// /// 是否连接 /// public bool Connected { get { bool state = ClientTcp.Connected; if (state == false) { TerminateThreadsTCPStream(); } if (state != IsConnected) { IsConnected = state; } return state; } private set { if (value == IsConnected) return; IsConnected = value; } } /// /// 断开连接 /// public virtual void Disconnect() { TerminateThreadsTCPStream(); Connected = false; ClientTcp.Close(); //ClientTcp.Dispose(); ClientTcp = new System.Net.Sockets.TcpClient(); //SetConnectStatusEvent("连接断开成功!"); } /// /// 结束线程与数据流 /// private void TerminateThreadsTCPStream() { RaskThreadIsStart = false; DataMonitoringThread = null; ConnectMonitoringThread = null; ClientStream?.Close(); ClientStream = null; } /// /// 获取客户端连接状态 /// /// private bool GetConnectedStatus() { return !((ClientTcp.Client.Poll(1000, SelectMode.SelectRead) && (ClientTcp.Client.Available == 0)) || !ClientTcp.Client.Connected); } /// /// 监测接收数据字符串 /// private async void MonitorRecevingData() { await Task.Run(() => { try { EventHandler DataReceivedHandler; while (RaskThreadIsStart) { if (!Connected) ClientConnect(); else { DataReceivedHandler = DataReceived; if (DataReceivedHandler != null) { if (ClientStream != null) { if (ClientStream.DataAvailable) { lock (LockHandler) { List datas = ReadOrigBytes(); if (datas != null) { if (datas.Count > 0) { for (int i = 0; i < datas.Count; i++) { if (datas[i].Length > 0) { DataReceivedHandler.Invoke(this, new TcpDataReceivedEventArgs() { Data = datas[i] }); } else { Thread.Sleep(2); continue; } } } else { Thread.Sleep(2); continue; } } else { Thread.Sleep(2); continue; } } } else { Thread.Sleep(2); continue; } } else { Thread.Sleep(2); continue; } } else { Thread.Sleep(2); continue; } } } } catch (Exception ex) { ex.ToString(); } }); } /// /// 读原始数据字节数组--解析成数组类型的数据帧格式 /// /// private List ReadOrigBytes() { List bytesResult = new List(); if (ClientStream != null) { ClientStream.ReadTimeout = ReadTimeout; while (true) { int readByte = 0; try { readByte = ClientStream.Read(FixedBuffer, 0, BufferSize); if (readByte == 0) break; else if (readByte >= 9) { bytesResult = GetReadResult(FixedBuffer, readByte); } if (!ClientStream.DataAvailable) break; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("警告: ReadRawBytes()引发异常: " + ex); return null; } } } return bytesResult; } /// /// 监测客户端连接 /// private void MonitorConnecting() { while (RaskThreadIsStart) { bool state = Connected; if (state != IsConnected) { IsConnected = state; if (state == false) { SetConnectStatusEvent("连接失败"); TerminateThreadsTCPStream(); } else { SetConnectStatusEvent("连接成功"); BufferSize = ClientTcp.ReceiveBufferSize; FixedBuffer = new byte[BufferSize]; RaskThreadIsStart = true; } } Thread.Sleep(20); } } public bool checksumDomainReceive(byte[] data) { bool bResult = false; int checksum = 0; for (int i = 6; i < data.Count() - 1; i++)//这里有校验域所以减一 { checksum += data[i]; } //foreach (byte b in data) //{ // checksum += b; //} // 取校验和的低8位 byte b1 = (byte)(checksum & 0xFF); byte b2 = data[data.Count() - 1]; if (data[data.Count() - 1] == (byte)(checksum & 0xFF)) bResult = true; return bResult; } private List GetReadResult(byte[] bytes, int readLen) { List lstResult = new List(); { byte[] bytesCppy = bytes;//操作此数组,不要动原始数组 //自定义解析 起始0xAA 0XF5-----会有很多包粘连到一起的情况 { if (readLen >= 9) { for (int i = 0; i < readLen; i++) { if (i + 1 <= readLen) { if (bytes[i] == 0xAA && bytes[i + 1] == 0xF5) { if (i + 2 < readLen) { int leng = ToUInt16(bytesCppy, i + 2);//帧的长度 // 创建一个新的byte数组来存储截取的数据 byte[] newBytes = new byte[leng]; // 使用Array.Copy方法将原始数组中的一部分复制到新数组 Array.Copy(bytesCppy, i, newBytes, 0, leng); //校验域是否正确 if (checksumDomainReceive(newBytes)) { var info = newBytes[4]; if ((info & (1 << 1)) != 0)//AES加密 { List byteList = newBytes.ToList(); byteList.Remove(8); byteList.Remove(8);//移除前面两个长度 newBytes= byteList.ToArray(); lstResult.Add(newBytes); } else //不加密 { lstResult.Add(newBytes); } } } } } } } } } { //int indexValue = 0; //List lstStartIndex = new List(); //搜索开始字节0x68的索引值 //int len = 0; //if (readLen >= 24) //{ // for (int i = 0; i < readLen; i++) // { // if (bytes[i] == 0x68) // { // lstStartIndex.Add(i); // } // } //} //int indexNum = lstStartIndex.Count; //if (indexNum > 0) //{ // for (int j = 0; j < indexNum; j++) // { // indexValue = lstStartIndex[j]; // if (indexValue < bytes.Count()) // { // if (j < indexNum - 1) // { // int datalen = lstStartIndex[j + 1] - lstStartIndex[j]; // //if (len == datalen) // //{ // // indexValue += len; // // byte[] data = new byte[datalen]; // // Array.Copy(bytes, lstStartIndex[j], data, 0, datalen); // // lstResult.Add(data); // //} // //else // //{ // // indexValue += len; // // byte[] data = new byte[len]; // // if (len <= bytes.Count()) // // { // // Array.Copy(bytes, lstStartIndex[j], data, 0, len); // // lstResult.Add(data); // // } // //} // byte[] data = new byte[datalen]; // if (len <= bytes.Count()) // { // Array.Copy(bytes, lstStartIndex[j], data, 0, datalen); // lstResult.Add(data); // } // } // else // { // int datalen = readLen - lstStartIndex[j]; // byte[] data = new byte[datalen]; // Array.Copy(bytes, lstStartIndex[j], data, 0, datalen); // lstResult.Add(data); // } // } // } //} } return lstResult; } ///// ///// 客户端读字节 ///// ///// 字节数组 //public List ReadBytes() //{ // lock (LockHandler) // { // if (!Connected) ClientConnect(); // return ReadOrigBytes(); // } //} /// /// 客户端写字节指令 /// /// public void Write(byte[] dataBytes) { if (ClientTcp != null) { if (ClientTcp.Connected) { try { if (DataSended != null) { EventHandler DataSendHandler; DataSendHandler = DataSended; DataSendHandler.Invoke(this, new TcpDataSendEventArgs() { Data = dataBytes }); } ClientStream.Write(dataBytes, 0, dataBytes.Length); ClientStream.Flush(); } catch (Exception ex) { ex.ToString(); } } } } private bool disposedValue = false; protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { TerminateThreadsTCPStream(); ClientTcp.Close(); ClientTcp = null; } disposedValue = true; } } public void Dispose() { Dispose(true); } private ushort ToUInt16(byte[] value, int offset) { return (ushort)(value[offset] + (value[offset + 1] << 8)); } } }