From d0ded5cd9bf5070a120bad58b5be21fe2ac6a4ff Mon Sep 17 00:00:00 2001
From: C3032 <C3032@BC3032>
Date: 星期六, 20 十二月 2025 16:41:09 +0800
Subject: [PATCH] test
---
IDViewer_2D/TcpServerManager.cs | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 272 insertions(+), 0 deletions(-)
diff --git a/IDViewer_2D/TcpServerManager.cs b/IDViewer_2D/TcpServerManager.cs
new file mode 100644
index 0000000..f7c6a7c
--- /dev/null
+++ b/IDViewer_2D/TcpServerManager.cs
@@ -0,0 +1,272 @@
+锘縰sing 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<Task<int[]>> _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<string, TcpClient> _connectedClients = new ConcurrentDictionary<string, TcpClient>();
+
+ public event Action<string> LogMessage;
+ public event Action<string, string> CommandReceived;
+ public event Action<string> ClientConnected;
+ public event Action<string> ClientDisconnected;
+
+ public TcpServerManager(bool enableHeartbeat, string heartbeatCommand, int heartbeatInterval,
+ Func<Task<int[]>> 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;
+ }
+ /// <summary>
+ /// TCP鏈嶅姟鍣ㄥ紑濮嬩睛鍚�
+ /// </summary>
+ /// <param name="ip">鏈嶅姟鍣↖P鍦板潃</param>
+ /// <param name="port">鏈嶅姟鍣ㄧ鍙�</param>
+ 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} 姝e父鏂紑");
+ 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)
+ {
+ // 姝e父鍙栨秷
+ }
+ 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();
+ }
+ }
+}
--
Gitblit v1.9.3