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);
}
}
}