using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Module.Socket.Tool { public class TcpClientBmsTool { TcpClient ClientTcp = new TcpClient(); NetworkStream ClientStream; private readonly object LockHandler = new object(); /// /// 确定的已接收缓存字节数组 /// private byte[] FixedBuffer; /// /// 上次接收剩余字节 /// private List RemainBuffer = new List(); /// /// 缓存字节长度 /// private int BufferSize; /// /// 客户端是否已经连接 /// private bool IsConnected = false; private Thread DataMonitoringThread; private Thread ConnectMonitoringThread; public event EventHandler ConnectedStatusChanged; public event EventHandler DataReceived; public event EventHandler DataSended; /// /// 客户端IP地址 /// public string ClientIP { get; set; } /// /// 客户端端口号 /// public int ClientPort { get; set; } /// /// 客户端任务线程是否已经开始运行 /// public bool RaskThreadIsStart { get; set; } = true; /// /// 数据接收事件是否被阻塞 /// public bool DataReceivedEventIsSuspend { get; set; } = false; /// /// 读数据超时时间(毫秒) /// public int ReadTimeout { get; set; } = 1000; public TcpClientBmsTool() { } public TcpClientBmsTool(string ipAddr, int port) { ClientIP = ipAddr; ClientPort = port; } /// /// 客户端连接 /// public virtual void ClientConnect() { try { Disconnect(); ClientTcp.Connect(ClientIP, ClientPort); 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客户端连接状态监测" + ClientPort.ToString(); ConnectMonitoringThread.Start(); DataMonitoringThread = new Thread(MonitorRecevingData); DataMonitoringThread.Name = "TCP客户端数据接收监测" + ClientPort.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 + "与服务端" + ClientIP.ToString() + ":" + ClientPort.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 = new System.Net.Sockets.TcpClient(); } /// /// 结束线程与数据流 /// 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(20); continue; } } } else { Thread.Sleep(20); continue; } } else { Thread.Sleep(20); continue; } } } else { Thread.Sleep(20); continue; } } else { Thread.Sleep(20); continue; } } else { Thread.Sleep(20); 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 > 6) { 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); } } private List GetReadResult(byte[] bytes, int readLen) { int indexValue = 0; List lstResult = new List(); List lstStartIndex = new List(); //搜索开始字节0x08的索引值 int len = 0; if (readLen >= 6) { for (int i = 0; i < readLen; i++) { if (bytes[i] == 0x88) { lstStartIndex.Add(i); } } } int indexNum = lstStartIndex.Count; if (indexNum > 0) { for (int j = 0; j < indexNum; j++) { if (indexValue < bytes.Count()) { //len = ToUInt16(bytes, indexValue + 1); len = 13; 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); } } } else { int datalen = readLen - lstStartIndex[j]; if (len == datalen) { 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 { 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)); } } }