using Common.Attributes; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows; using static Common.Attributes.ATSCommandAttribute; namespace DeviceCommand.Base { [ATSCommand] [DeviceCategory("全部驱动")] // 添加分类属性 public class Tcp { public string IPAddress { get; set; } = "127.0.0.1"; public int Port { get; set; } = 502; public int SendTimeout { get; set; } = 3000; public int ReceiveTimeout { get; set; } = 3000; public TcpClient TcpClient { get; set; } = new(); public Tcp CreateDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000) { IPAddress = ipAddress; Port = port; SendTimeout = sendTimeout; ReceiveTimeout = receiveTimeout; return this; } /// /// 修改TCP连接参数 /// /// /// IP地址 /// 端口号 /// 发送超时时间 /// 接收超时时间 public static void ChangeDeviceConfig(Tcp tcp, string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000) { tcp.IPAddress = ipAddress; tcp.Port = port; if (sendTimeout > 0) { tcp.SendTimeout = sendTimeout; } if (receiveTimeout > 0) { tcp.ReceiveTimeout = receiveTimeout; } } /// /// 连接TCP设备 /// /// TCP设备对象 /// 取消令牌 /// 连接结果 public static async Task ConnectAsync(Tcp tcp, CancellationToken ct = default) { if (!tcp.TcpClient.Connected) { tcp.TcpClient.Close(); tcp.TcpClient.Dispose(); tcp.TcpClient = new TcpClient(); await tcp.TcpClient.ConnectAsync(tcp.IPAddress, tcp.Port, ct); } else { // 获取当前连接的远程端点 var remoteEndPoint = (IPEndPoint)tcp.TcpClient.Client.RemoteEndPoint!; // 比较IP地址和端口 var ip = remoteEndPoint.Address.MapToIPv4().ToString(); bool isSameAddress = ip.Equals(tcp.IPAddress); bool isSamePort = remoteEndPoint.Port == tcp.Port; // 如果端点不匹配则断开重连 if (!isSameAddress || !isSamePort) { tcp.TcpClient.Close(); tcp.TcpClient.Dispose(); tcp.TcpClient = new TcpClient(); await tcp.TcpClient.ConnectAsync(tcp.IPAddress, tcp.Port, ct); } } return true; } /// /// 关闭TCP连接 /// /// TCP设备对象 public static void Close(Tcp tcp) { tcp.TcpClient.Close(); } /// /// 发送字节数组到TCP设备 /// /// TCP设备对象 /// 要发送的字节数组 /// 取消令牌 public static async Task SendAsync(Tcp tcp, byte[] bytes, CancellationToken ct = default) { var timeoutMs = tcp.SendTimeout; if (timeoutMs <= 0) { await tcp.TcpClient.Client.SendAsync(bytes, ct); return; } var sendTask = tcp.TcpClient.Client.SendAsync(bytes, ct).AsTask(); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(sendTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"TCP通讯异常:写入操作在 {timeoutMs} ms内未完成"); } await sendTask; } /// /// 发送字符串到TCP设备 /// /// TCP设备对象 /// 要发送的字符串 /// 取消令牌 public static async Task SendAsync(Tcp tcp, string str, CancellationToken ct = default) { await SendAsync(tcp, Encoding.UTF8.GetBytes(str), ct); } /// /// 接收指定长度的字节数组 /// /// TCP设备对象 /// 接收缓冲区 /// 取消令牌 /// 接收到的字节数组 public static async Task ReadAsync(Tcp tcp, byte[] buffer, CancellationToken ct = default) { if (!tcp.TcpClient.Connected) return null; var timeoutMs = tcp.ReceiveTimeout; if (timeoutMs <= 0) { return await ReadBytes(tcp, buffer, ct); } var readTask = ReadBytes(tcp, buffer, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(readTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"TCP通讯异常:读取操作在 {timeoutMs} ms内未完成"); } return await readTask; } private static async Task ReadBytes(Tcp tcp, byte[] buffer, CancellationToken ct) { NetworkStream stream = tcp.TcpClient.GetStream(); int bytesRead = 0; while (bytesRead < buffer.Length) { int read = await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead, ct); if (read == 0) return null; bytesRead += read; } return buffer; } /// /// 接收字符串直到遇到分隔符 /// /// TCP设备对象 /// 分隔符 /// 取消令牌 /// 接收到的字符串 public static async Task ReadAsync(Tcp tcp, string delimiter = "\n", CancellationToken ct = default) { delimiter ??= "\n"; var timeoutMs = tcp.ReceiveTimeout; if (timeoutMs <= 0) { return await ReadString(tcp, delimiter, ct); } var readTask = ReadString(tcp, delimiter, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(readTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"TCP通讯异常:读取操作在 {timeoutMs} ms内未完成"); } return await readTask; } private static async Task ReadString(Tcp tcp, string delimiter, CancellationToken ct) { NetworkStream stream = tcp.TcpClient.GetStream(); MemoryStream memoryStream = new(); byte[] buffer = new byte[2048]; int bytesRead; while ((bytesRead = await stream.ReadAsync(buffer, ct)) > 0) { memoryStream.Write(buffer, 0, bytesRead); string data = Encoding.UTF8.GetString(memoryStream.ToArray()); int lineEndIndex = data.IndexOf(delimiter); if (lineEndIndex >= 0) { return data[..lineEndIndex].Trim(); } } return null; } /// /// 发送并接收数据 /// /// TCP设备对象 /// 要发送的字符串 /// 结束符 /// 取消令牌 /// 接收到的响应 public async Task WriteRead(Tcp tcp, string str, string endstr, CancellationToken ct = default) { await SendAsync(tcp, str, ct); return await ReadAsync(tcp, endstr, ct); } /// /// 连接TCP设备 /// /// 取消令牌 /// 连接结果 public async Task ConnectAsync(CancellationToken ct = default) { return await ConnectAsync(this, ct); } } }