From fe2a1e74780259605cd230e6f9c629c3dd7fdf15 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 10 四月 2026 20:19:06 +0800
Subject: [PATCH] feat: 添加消防任务支持并修复堆垛机状态处理

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs |  140 +++++++++++++++++++++++++++-------------------
 1 files changed, 83 insertions(+), 57 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
index d3c401b..afaa8ec 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
@@ -1,53 +1,63 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Net;
 using System.Net.Sockets;
-using System.Threading;
-using System.Threading.Tasks;
+using System.Text;
+using System.Text.Json;
+using System.IO;
+using WIDESEAWCS_Core.LogHelper;
 
 namespace WIDESEAWCS_Tasks.SocketServer
 {
     public partial class TcpSocketServer
     {
         /// <summary>
-        /// 异步启动TCP服务器,使其开始接受传入的客户端连接。
+        /// 寮傛鍚姩 TCP Socket 鏈嶅姟鍣�
         /// </summary>
-        /// <remarks>如果服务器已在运行或通过配置禁用,此方法将立即返回而不启动服务器。
-        /// 后续的客户端监控和接受操作在后台任务中运行。此方法不会阻塞调用线程。</remarks>
-        /// <param name="cancellationToken">可用于请求取消服务器启动及后续后台操作的取消令牌。</param>
-        /// <returns>表示异步启动操作的任务。当服务器开始监听连接时任务完成。</returns>
-        public Task StartAsync(CancellationToken cancellationToken)
+        /// <remarks>
+        /// 鍒涘缓 TCP 鐩戝惉鍣ㄥ苟寮�濮嬫帴鍙楀鎴风杩炴帴銆�
+        /// 濡傛灉鏈嶅姟鍣ㄥ凡鍦ㄨ繍琛屾垨琚鐢紝鐩存帴杩斿洖銆�
+        /// 鍚姩鍚庡惎鍔ㄦ帴鍙楀惊鐜拰瀹㈡埛绔洃鎺т换鍔°��
+        /// </remarks>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <returns>鍚姩浠诲姟</returns>
+        public async Task StartAsync(CancellationToken cancellationToken)
         {
             if (IsRunning || !_options.Enabled)
             {
-                return Task.CompletedTask;
+                return;
             }
 
+            // 瑙f瀽鐩戝惉鍦板潃
             IPAddress ipAddress = IPAddress.Any;
             if (IPAddress.TryParse(_options.IpAddress, out IPAddress? parsedAddress))
             {
                 ipAddress = parsedAddress;
             }
 
+            await Task.Delay(5000);
+
+            // 鍒涘缓鐩戝惉鍣�
             _listener = new TcpListener(ipAddress, _options.Port);
             _listener.Start(_options.Backlog);
             _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
             IsRunning = true;
 
+            // 鍚姩鎺ュ彈瀹㈡埛绔繛鎺ュ惊鐜�
             _ = AcceptLoopAsync(_cts.Token);
+
+            // 鍚姩瀹㈡埛绔洃鎺т换鍔★紙妫�鏌ョ┖闂茶秴鏃讹級
             _monitorTask = Task.Run(() => MonitorClientsAsync(_cts.Token));
 
-            return Task.CompletedTask;
+            return;
         }
 
-        //// <summary>
-        /// 异步停止服务器并等待所有活动客户端连接完成。
+        /// <summary>
+        /// 寮傛鍋滄 TCP Socket 鏈嶅姟鍣�
         /// </summary>
-        /// <remarks>如果服务器未运行,此方法将立即返回而不执行任何操作。
-        /// 此方法确保所有客户端任务完成后才将服务器标记为已停止。</remarks>
-        /// <param name="cancellationToken">可用于在完成前取消停止操作的取消令牌。</param>
-        /// <returns>表示异步停止操作的任务。</returns>
+        /// <remarks>
+        /// 鍋滄鎺ュ彈鏂拌繛鎺ワ紝绛夊緟鎵�鏈夊鎴风浠诲姟瀹屾垚銆�
+        /// </remarks>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <returns>鍋滄浠诲姟</returns>
         public async Task StopAsync(CancellationToken cancellationToken)
         {
             if (!IsRunning)
@@ -55,9 +65,13 @@
                 return;
             }
 
+            // 鍙戦�佸彇娑堜俊鍙�
             _cts?.Cancel();
+
+            // 鍋滄鐩戝惉
             _listener?.Stop();
 
+            // 绛夊緟鎵�鏈夊鎴风浠诲姟瀹屾垚
             Task[] tasks;
             lock (_syncRoot)
             {
@@ -73,12 +87,16 @@
         }
 
         /// <summary>
-        /// 持续接受传入的TCP客户端连接,直到请求取消。
+        /// 寮傛鎺ュ彈瀹㈡埛绔繛鎺ョ殑涓诲惊鐜�
         /// </summary>
-        /// <remarks>此方法旨在后台运行以处理新的客户端连接。
-        /// 如果监听器被释放或通过提供的令牌请求取消,循环将退出。</remarks>
-        /// <param name="cancellationToken">可用于请求取消接受循环的令牌。当请求取消时,循环将立即终止。</param>
-        /// <returns>表示异步接受循环操作的任务。</returns>
+        /// <summary>
+        /// 寮傛鎺ュ彈瀹㈡埛绔繛鎺ョ殑涓诲惊鐜�
+        /// </summary>
+        /// <remarks>
+        /// 鍦ㄥ悗鍙扮嚎绋嬩腑鎸佺画鎺ュ彈鏂扮殑瀹㈡埛绔繛鎺ャ��
+        /// 褰撴湁鏂拌繛鎺ユ椂锛屽皢鍏舵坊鍔犲埌瀹㈡埛绔瓧鍏稿苟鍚姩娑堟伅澶勭悊浠诲姟銆�
+        /// </remarks>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
         private async Task AcceptLoopAsync(CancellationToken cancellationToken)
         {
             while (!cancellationToken.IsCancellationRequested)
@@ -86,30 +104,23 @@
                 TcpClient? client = null;
                 try
                 {
+                    // 绛夊緟瀹㈡埛绔繛鎺�
                     client = await _listener!.AcceptTcpClientAsync().WaitAsync(cancellationToken);
+                    QuartzLogger.Info($"瀹㈡埛绔繛鎺�:{client.Client.RemoteEndPoint.ToString()}");
                 }
-                catch (OperationCanceledException)
-                {
-                    break;
-                }
-                catch (ObjectDisposedException)
-                {
-                    break;
-                }
+                catch (OperationCanceledException) { break; }
+                catch (ObjectDisposedException) { break; }
                 catch
                 {
-                    if (cancellationToken.IsCancellationRequested)
-                    {
-                        break;
-                    }
+                    if (cancellationToken.IsCancellationRequested) break;
                 }
 
-                if (client == null)
-                {
-                    continue;
-                }
+                if (client == null) continue;
 
+                // 鐢熸垚瀹㈡埛绔� ID锛堜娇鐢ㄨ繙绋嬬鐐瑰湴鍧�锛�
                 string clientId = GetClientId(client);
+
+                // 娣诲姞鍒板鎴风瀛楀吀
                 lock (_syncRoot)
                 {
                     _clients[clientId] = client;
@@ -119,30 +130,41 @@
         }
 
         /// <summary>
-        /// 从内部集合中移除指定标识符的客户端,并释放相关资源。
+        /// 绉婚櫎瀹㈡埛绔繛鎺�
         /// </summary>
-        /// <remarks>此方法关闭客户端连接,释放任何关联的锁,并移除对客户端的所有引用,
-        /// 包括设备绑定和编码信息。通过对内部同步对象加锁确保线程安全。</remarks>
-        /// <param name="clientId">要移除的客户端的唯一标识符。不能为null或空。</param>
+        /// <remarks>
+        /// 鍏抽棴瀹㈡埛绔繛鎺ュ苟娓呯悊鐩稿叧璧勬簮锛�
+        /// - 鍏抽棴 TcpClient
+        /// - 閲婃斁淇″彿閲�
+        /// - 绉婚櫎娲昏穬鏃堕棿鍜岀紪鐮佽褰�
+        /// - 绉婚櫎璁惧缁戝畾
+        /// </remarks>
+        /// <param name="clientId">瑕佺Щ闄ょ殑瀹㈡埛绔敮涓�鏍囪瘑</param>
         private void RemoveClient(string clientId)
         {
             lock (_syncRoot)
             {
+                // 鍏抽棴骞剁Щ闄ゅ鎴风杩炴帴
                 if (_clients.TryGetValue(clientId, out var client))
                 {
                     try { client.Close(); } catch { }
                     _clients.Remove(clientId);
                 }
 
+                // 閲婃斁淇″彿閲�
                 if (_clientLocks.TryGetValue(clientId, out var sem))
                 {
                     _clientLocks.Remove(clientId);
                     sem.Dispose();
                 }
 
+                // 绉婚櫎娲昏穬鏃堕棿璁板綍
                 _clientLastActive.Remove(clientId);
+
+                // 绉婚櫎缂栫爜璁板綍
                 _clientEncodings.Remove(clientId);
 
+                // 绉婚櫎璁惧缁戝畾
                 var deviceIds = _deviceBindings.Where(kv => kv.Value == clientId).Select(kv => kv.Key).ToList();
                 foreach (var deviceId in deviceIds)
                 {
@@ -152,12 +174,13 @@
         }
 
         /// <summary>
-        /// 异步监控已连接的客户端,并断开超过配置超时时间闲置的客户端连接。
+        /// 寮傛鐩戞帶瀹㈡埛绔┖闂茶秴鏃�
         /// </summary>
-        /// <remarks>此方法持续检查闲置客户端,如果其不活动时间超过指定的空闲超时,则断开连接。
-        /// 监控循环将持续运行,直到通过提供的令牌请求取消。</remarks>
-        /// <param name="cancellationToken">可用于请求终止监控循环的取消令牌。</param>
-        /// <returns>表示异步监控操作的任务。</returns>
+        /// <remarks>
+        /// 瀹氭湡妫�鏌ユ墍鏈夊鎴风鐨勬渶鍚庢椿璺冩椂闂达紝
+        /// 濡傛灉瓒呰繃绌洪棽瓒呮椂鏃堕棿锛屾柇寮�璇ュ鎴风杩炴帴銆�
+        /// </remarks>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
         private async Task MonitorClientsAsync(CancellationToken cancellationToken)
         {
             while (!cancellationToken.IsCancellationRequested)
@@ -169,6 +192,7 @@
                     {
                         foreach (var kv in _clientLastActive)
                         {
+                            // 妫�鏌ユ槸鍚﹁秴杩囩┖闂茶秴鏃�
                             if (_options.IdleTimeoutSeconds > 0 && DateTime.Now - kv.Value > TimeSpan.FromSeconds(_options.IdleTimeoutSeconds))
                             {
                                 toRemove.Add(kv.Key);
@@ -176,27 +200,29 @@
                         }
                     }
 
+                    // 鏂紑瓒呮椂鐨勫鎴风
                     foreach (var cid in toRemove)
                     {
                         RemoveClient(cid);
                         Log($"[{DateTime.Now}] TcpSocketServer disconnect idle client {cid}");
                     }
                 }
-                catch
-                {
-                }
+                catch { }
 
+                // 姣忕妫�鏌ヤ竴娆�
                 try { await Task.Delay(1000, cancellationToken); } catch { }
             }
         }
 
         /// <summary>
-        /// 基于远程终端点获取指定TCP客户端的唯一标识符字符串。
+        /// 鑾峰彇瀹㈡埛绔敮涓�鏍囪瘑
         /// </summary>
-        /// <remarks>返回的标识符适用于在日志记录或跟踪场景中区分客户端。
-        /// 如果客户端的远程终端点不可用,将生成GUID以确保唯一性。</remarks>
-        /// <param name="client">要获取标识符的TCP客户端。不能为null。</param>
-        /// <returns>表示客户端远程终端点的字符串(如果可用);否则为生成的新GUID字符串。</returns>
+        /// <remarks>
+        /// 浣跨敤瀹㈡埛绔殑杩滅▼绔偣鍦板潃浣滀负鏍囪瘑銆�
+        /// 濡傛灉杩滅▼绔偣涓嶅彲鐢紝鐢熸垚闅忔満 GUID銆�
+        /// </remarks>
+        /// <param name="client">TCP 瀹㈡埛绔�</param>
+        /// <returns>瀹㈡埛绔爣璇嗗瓧绗︿覆</returns>
         public static string GetClientId(TcpClient client)
         {
             return client.Client.RemoteEndPoint?.ToString() ?? Guid.NewGuid().ToString();

--
Gitblit v1.9.3