using SmartScanner.ViewModel; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SmartScanner { public class TcpServerManager : IDisposable { private TcpListener _listener; public static bool _isRunning; private CancellationTokenSource _cts; private Func> _imageProcessingHandler; // 图像处理委托 private int _outputIOCount; // 输出IO数量 // 心跳配置 public bool EnableHeartbeat { get; private set; } public string HeartbeatCommand { get; private set; } public int HeartbeatInterval { get; private set; } // 客户端列表管理(如果需要跟踪多个客户端) // private ConcurrentDictionary _connectedClients = new ConcurrentDictionary(); public event Action LogMessage; public event Action CommandReceived; public event Action ClientConnected; public event Action ClientDisconnected; public TcpServerManager(bool enableHeartbeat, string heartbeatCommand, int heartbeatInterval, Func> imageProcessingHandler, int outputIOCount) { EnableHeartbeat = enableHeartbeat; HeartbeatCommand = heartbeatCommand ?? "heartBeat"; HeartbeatInterval = heartbeatInterval > 0 ? heartbeatInterval : 1000; _imageProcessingHandler = imageProcessingHandler ?? throw new ArgumentNullException(nameof(imageProcessingHandler)); _outputIOCount = outputIOCount > 0 ? outputIOCount : 1; } /// /// TCP服务器开始侦听 /// /// 服务器IP地址 /// 服务器端口 public async Task StartAsync(string ip, int port) { if (port == -1) return; _cts = new CancellationTokenSource(); _isRunning = true; _listener = new TcpListener(IPAddress.Parse(ip), port); _listener.Start(); LogMessage?.Invoke($"TCP服务器已启动,开始侦听 {ip}:{port}"); LogMessage?.Invoke($"心跳检测: {(EnableHeartbeat ? "已启用" : "已禁用")}"); if (EnableHeartbeat) { LogMessage?.Invoke($"心跳指令: {HeartbeatCommand}, 间隔: {HeartbeatInterval}ms"); } try { while (_isRunning) { var acceptTask = _listener.AcceptTcpClientAsync(); var cancelTask = Task.Delay(-1, _cts.Token); var completedTask = await Task.WhenAny(acceptTask, cancelTask); if (completedTask == cancelTask || _cts.Token.IsCancellationRequested) { break; } var client = await acceptTask; _ = HandleClientAsync(client); } } catch (Exception ex) { LogMessage?.Invoke($"服务器错误: {ex.Message}"); } } private async Task HandleClientAsync(TcpClient client) { var clientId = client.Client.RemoteEndPoint?.ToString() ?? "未知客户端"; ClientConnected?.Invoke(clientId); LogMessage?.Invoke($"客户端已连接: {clientId}"); try { using (client) using (var stream = client.GetStream()) { // 使用NetworkStream读取 byte[] buffer = new byte[4096]; MemoryStream ms = new MemoryStream(); while (!_cts.IsCancellationRequested && client.Connected) { // 检查数据是否可用 if (!stream.DataAvailable) { await Task.Delay(10, _cts.Token); // 短暂等待 continue; } // 同步读取方式 int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) // 连接已关闭 { LogMessage?.Invoke($"客户端 {clientId} 正常断开"); break; } ms.Write(buffer, 0, bytesRead); // 处理完整消息(消息以换行符结尾) string receivedData = Encoding.ASCII.GetString(ms.ToArray()); //if (receivedData.Contains('\n')) //{ string[] messages = receivedData.Split('\n'); for (int i = 0; i < messages.Length - 1; i++) // 最后一段可能不完整 { string message = messages[i].Trim(); if (!string.IsNullOrEmpty(message)) { await ProcessMessageAsync(message, stream, clientId); } } // 保留不完整的部分 ms.SetLength(0); if (!string.IsNullOrEmpty(messages.Last())) { ms.Write(Encoding.ASCII.GetBytes(messages.Last()), 0, messages.Last().Length); } //} } } } catch (Exception ex) { LogMessage?.Invoke($"处理客户端 {clientId} 时出错: {ex.Message}"); } finally { ClientDisconnected?.Invoke(clientId); LogMessage?.Invoke($"客户端断开: {clientId}"); } } private async Task ProcessMessageAsync(string message, NetworkStream stream, string clientId) { LogMessage?.Invoke($"来自 {clientId}: {message}"); Console.WriteLine($"{DateTime.Now:HH:mm:ss:fff}:检测到触发信号{message}"); EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:检测到触发信号{message}"); // 处理心跳 if (EnableHeartbeat && message == HeartbeatCommand) { byte[] ack = Encoding.ASCII.GetBytes($"{HeartbeatCommand}_ACK\n"); await stream.WriteAsync(ack, 0, ack.Length); return; } // 处理业务消息 var parts = message.Split(','); if (parts.Length >= 2 && int.TryParse(parts[0], out var functionCode)) { // 处理触发信号 (暂定功能码为3,待后续与客户沟通) if (functionCode == 3) { await HandleTriggerCommand(stream, clientId); } else { // 其他功能码处理 var response = $"{functionCode},0,Invalid function code\n"; byte[] responseBytes = Encoding.ASCII.GetBytes(response); await stream.WriteAsync(responseBytes, 0, responseBytes.Length); } } } private async Task HandleTriggerCommand(NetworkStream stream, string clientId) { try { LogMessage?.Invoke($"开始处理触发命令,进行图像采集和推理..."); // 调用图像处理委托 int[] processingResults = await _imageProcessingHandler() .ConfigureAwait(false); // 避免死锁 if (processingResults == null || processingResults.Length != _outputIOCount) { throw new InvalidOperationException($"图像处理结果无效,预期{_outputIOCount}个输出,实际得到{processingResults?.Length ?? 0}"); } // 构建响应消息 var responseBuilder = new StringBuilder(); responseBuilder.Append("3,"); // 功能号 responseBuilder.Append(_outputIOCount); // 输出IO数 // 添加每个点位的处理结果 foreach (var result in processingResults) { responseBuilder.Append($",{result}"); } responseBuilder.Append("\n"); // 结束符 string response = responseBuilder.ToString(); LogMessage?.Invoke($"返回结果: {response.Trim()}"); EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:检测完成,返回结果{response.Trim()}"); // 发送响应 byte[] responseBytes = Encoding.ASCII.GetBytes(response); await stream.WriteAsync(responseBytes, 0, responseBytes.Length); } catch (Exception ex) { LogMessage?.Invoke($"处理触发命令时出错: {ex.Message}"); // 发送错误响应 var errorResponse = $"3,0,Error: {ex.Message}\n"; byte[] errorBytes = Encoding.ASCII.GetBytes(errorResponse); await stream.WriteAsync(errorBytes, 0, errorBytes.Length); } } private async Task StartHeartbeatAsync(StreamWriter writer, CancellationToken token) { try { while (!token.IsCancellationRequested) { await writer.WriteLineAsync(HeartbeatCommand); await Task.Delay(HeartbeatInterval, token); } } catch (OperationCanceledException) { // 正常取消 } catch (Exception ex) { LogMessage?.Invoke($"心跳任务错误: {ex.Message}"); } } public void Stop() { _isRunning = false; _cts?.Cancel(); try { _listener?.Stop(); LogMessage?.Invoke("TCP服务器已停止"); } catch (Exception ex) { LogMessage?.Invoke($"停止服务器时出错: {ex.Message}"); } } public void Dispose() { Stop(); _cts?.Dispose(); } } }