From fd18eaba5e1c086a588509371f91310e7aafff9c Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期三, 08 四月 2026 22:06:59 +0800
Subject: [PATCH] refactor: 升级多个项目目标框架至.NET 8.0

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs |  182 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 169 insertions(+), 13 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
index 9f186e4..571cd45 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -1,16 +1,28 @@
-using HslCommunication.Core.IMessage;
-using System;
 using System.Net.Sockets;
 using System.Text;
 using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using WIDESEAWCS_QuartzJob;
+using System.IO;
 
 namespace WIDESEAWCS_Tasks.SocketServer
 {
     public partial class TcpSocketServer
     {
+        /// <summary>
+        /// 澶勭悊瀹㈡埛绔繛鎺ョ殑娑堟伅寰幆
+        /// </summary>
+        /// <remarks>
+        /// 鎸佺画鎺ユ敹瀹㈡埛绔秷鎭紝鐩村埌杩炴帴鏂紑鎴栧彇娑堛��
+        /// 澶勭悊娴佺▼锛�
+        /// 1. 鎺ユ敹娑堟伅锛堝抚瑙f瀽锛�
+        /// 2. 鏇存柊瀹㈡埛绔姸鎬侊紙娲昏穬鏃堕棿銆佺紪鐮侊級
+        /// 3. 澶勭悊璁惧娉ㄥ唽
+        /// 4. 瑙﹀彂 MessageReceived 浜嬩欢
+        /// 杩炴帴鏂紑鏃舵竻鐞嗚祫婧愬苟瑙﹀彂 RobotReceived 浜嬩欢銆�
+        /// </remarks>
+        /// <param name="client">TCP 瀹㈡埛绔繛鎺�</param>
+        /// <param name="clientId">瀹㈡埛绔敮涓�鏍囪瘑</param>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <param name="robotCrane">鏈哄櫒浜虹姸鎬�</param>
         public async Task HandleClientAsync(TcpClient client, string clientId, CancellationToken cancellationToken, RobotSocketState robotCrane)
         {
             using (client)
@@ -21,18 +33,21 @@
                 CancellationTokenSource? localCts = null;
                 if (_options.EnableHeartbeat || _options.IdleTimeoutSeconds > 0)
                 {
+                    // 鍒涘缓閾炬帴鐨勫彇娑堜护鐗屾簮
                     localCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                 }
 
                 try
                 {
+                    // 娑堟伅鎺ユ敹寰幆
                     while (!cancellationToken.IsCancellationRequested && client.Connected)
                     {
                         string? message;
                         try
                         {
                             var ct = localCts?.Token ?? cancellationToken;
-                            message = await reader.ReadLineAsync().WaitAsync(ct);
+                            // 鎺ユ敹瀹屾暣娑堟伅锛堝抚瑙f瀽锛�
+                            message = await ReceiveFullMessageAsync(networkStream, _textEncoding, ct);
                         }
                         catch (OperationCanceledException)
                         {
@@ -44,23 +59,33 @@
                             break;
                         }
 
+                        // 鏇存柊瀹㈡埛绔姸鎬�
                         UpdateClientStatus(clientId, message);
 
                         string messageLower = message.ToLowerInvariant();
 
+                        // 澶勭悊娉ㄥ唽娑堟伅
                         if (TryHandleRegister(messageLower, message, clientId, networkStream, cancellationToken))
                         {
                             continue;
                         }
 
+                        // 瑙﹀彂娑堟伅鎺ユ敹浜嬩欢
                         if (MessageReceived != null)
                         {
-                            try { _ = MessageReceived.Invoke(message, false, client, robotCrane); } catch { }
+                            try
+                            {
+                                // 鍒ゆ柇鏄惁涓� JSON 鏍煎紡
+                                bool isJsonFormat = TryParseJsonSilent(message);
+                                _ = MessageReceived.Invoke(message, isJsonFormat, client, robotCrane);
+                            }
+                            catch { }
                         }
                     }
                 }
                 finally
                 {
+                    // 娓呯悊璧勬簮
                     try { localCts?.Cancel(); localCts?.Dispose(); } catch { }
                     RemoveClient(clientId);
                     try { _ = RobotReceived.Invoke(clientId); } catch { }
@@ -68,6 +93,19 @@
             }
         }
 
+        /// <summary>
+        /// 澶勭悊璁惧娉ㄥ唽娑堟伅
+        /// </summary>
+        /// <remarks>
+        /// 娉ㄥ唽娑堟伅鏍煎紡锛歳egister,{deviceId}
+        /// 灏嗚澶� ID 缁戝畾鍒板綋鍓嶅鎴风 ID銆�
+        /// </remarks>
+        /// <param name="messageLower">娑堟伅灏忓啓鐗堟湰</param>
+        /// <param name="message">鍘熷娑堟伅</param>
+        /// <param name="clientId">瀹㈡埛绔� ID</param>
+        /// <param name="networkStream">缃戠粶娴�</param>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <returns>鏄惁澶勭悊浜嗘敞鍐屾秷鎭�</returns>
         private bool TryHandleRegister(string messageLower, string message, string clientId, NetworkStream networkStream, CancellationToken cancellationToken)
         {
             if (!messageLower.StartsWith("register,"))
@@ -75,30 +113,45 @@
                 return false;
             }
 
+            // 鎻愬彇璁惧 ID
             string deviceId = message.Substring("register,".Length).Trim();
             if (!string.IsNullOrEmpty(deviceId))
             {
                 lock (_syncRoot)
                 {
+                    // 缁戝畾璁惧鍒板鎴风
                     _deviceBindings[deviceId] = clientId;
                 }
 
+                // 鍥炲娉ㄥ唽鎴愬姛
                 _ = WriteToClientAsync(clientId, networkStream, $"Registered,{deviceId}", cancellationToken);
             }
 
             return true;
         }
 
+        /// <summary>
+        /// 鏇存柊瀹㈡埛绔姸鎬�
+        /// </summary>
+        /// <remarks>
+        /// 鏇存柊鏈�鍚庢椿璺冩椂闂村拰瀛楃缂栫爜銆�
+        /// 濡傛灉寮�鍚簡鑷姩缂栫爜妫�娴嬶紝鏍规嵁娑堟伅鍐呭鍒ゆ柇鏄� UTF-8 杩樻槸 GBK銆�
+        /// </remarks>
+        /// <param name="clientId">瀹㈡埛绔� ID</param>
+        /// <param name="message">鏈�鏂版帴鏀剁殑娑堟伅</param>
         private void UpdateClientStatus(string clientId, string message)
         {
             lock (_syncRoot)
             {
+                // 鏇存柊鏈�鍚庢椿璺冩椂闂�
                 _clientLastActive[clientId] = DateTime.Now;
 
+                // 濡傛灉杩樻病鏈夎褰曠紪鐮�
                 if (!_clientEncodings.ContainsKey(clientId))
                 {
                     if (_options.AutoDetectEncoding && _autoDetectedGb2312 != null)
                     {
+                        // 鑷姩妫�娴嬬紪鐮侊細JSON 鎴� UTF-8 瀛楄妭鐗瑰緛鍒欑敤 UTF-8锛屽惁鍒欑敤 GBK
                         bool isUtf8 = TryParseJsonSilent(message) || IsLikelyUtf8(_textEncoding.GetBytes(message));
                         _clientEncodings[clientId] = isUtf8 ? _textEncoding : _autoDetectedGb2312;
                     }
@@ -110,6 +163,12 @@
             }
         }
 
+        /// <summary>
+        /// 寮傛鍙戦�佹秷鎭埌瀹㈡埛绔�
+        /// </summary>
+        /// <remarks>
+        /// 鍐呴儴鏂规硶锛屼笉浣跨敤甯ф牸寮忥紝鐩存帴鍙戦�佸師濮嬫秷鎭��
+        /// </remarks>
         private async Task WriteToClientAsync(string clientId, NetworkStream networkStream, string message, CancellationToken cancellationToken)
         {
             SemaphoreSlim? sem = null;
@@ -125,7 +184,8 @@
             if (sem != null) await sem.WaitAsync(cancellationToken);
             try
             {
-                var data = enc.GetBytes(message + "\n");
+                var framedMessage = BuildFramedMessage(message);
+                var data = enc.GetBytes(framedMessage);
                 await networkStream.WriteAsync(data, 0, data.Length, cancellationToken);
             }
             finally
@@ -134,6 +194,30 @@
             }
         }
 
+        /// <summary>
+        /// 鏋勫缓甯ф秷鎭�
+        /// </summary>
+        /// <remarks>
+        /// 鍦ㄦ秷鎭墠鍚庢坊鍔犲ご灏炬爣璇嗐��
+        /// </remarks>
+        /// <param name="message">鍘熷娑堟伅</param>
+        /// <returns>甯﹀抚鏍囪瘑鐨勬秷鎭�</returns>
+        private string BuildFramedMessage(string message)
+        {
+            var header = _options.MessageHeader ?? string.Empty;
+            var footer = _options.MessageFooter ?? string.Empty;
+            return header + (message ?? string.Empty) + footer;
+        }
+
+        /// <summary>
+        /// 闈欓粯灏濊瘯瑙f瀽 JSON
+        /// </summary>
+        /// <remarks>
+        /// 鍒ゆ柇娑堟伅鏄惁浠� { 鎴� [ 寮�澶达紝濡傛灉鏄垯灏濊瘯瑙f瀽銆�
+        /// 瑙f瀽澶辫触涓嶆姏寮傚父銆�
+        /// </remarks>
+        /// <param name="message">娑堟伅鍐呭</param>
+        /// <returns>鏄惁鏄湁鏁堢殑 JSON 鏍煎紡</returns>
         private static bool TryParseJsonSilent(string message)
         {
             if (string.IsNullOrWhiteSpace(message)) return false;
@@ -142,26 +226,36 @@
             try { JsonDocument.Parse(message); return true; } catch { return false; }
         }
 
+        /// <summary>
+        /// 鍒ゆ柇瀛楄妭鏁扮粍鏄惁涓� UTF-8 缂栫爜
+        /// </summary>
+        /// <remarks>
+        /// 閫氳繃妫�鏌ュ瓧鑺傚簭鍒楁槸鍚︾鍚� UTF-8 澶氬瓧鑺傚瓧绗︾殑缂栫爜瑙勫垯銆�
+        /// </remarks>
+        /// <param name="data">瀛楄妭鏁扮粍</param>
+        /// <returns>鏄惁鍙兘鏄� UTF-8 缂栫爜</returns>
         private static bool IsLikelyUtf8(byte[] data)
         {
             int i = 0;
             while (i < data.Length)
             {
                 byte b = data[i];
-                if (b <= 0x7F) { i++; continue; }
-                if (b >= 0xC2 && b <= 0xDF)
+                if (b <= 0x7F) { i++; continue; }  // ASCII 瀛楃
+
+                // 妫�鏌ュ瀛楄妭瀛楃
+                if (b >= 0xC2 && b <= 0xDF)  // 2瀛楄妭瀛楃
                 {
                     if (i + 1 >= data.Length) return false;
                     if ((data[i + 1] & 0xC0) != 0x80) return false;
                     i += 2; continue;
                 }
-                if (b >= 0xE0 && b <= 0xEF)
+                if (b >= 0xE0 && b <= 0xEF)  // 3瀛楄妭瀛楃
                 {
                     if (i + 2 >= data.Length) return false;
                     if ((data[i + 1] & 0xC0) != 0x80 || (data[i + 2] & 0xC0) != 0x80) return false;
                     i += 3; continue;
                 }
-                if (b >= 0xF0 && b <= 0xF4)
+                if (b >= 0xF0 && b <= 0xF4)  // 4瀛楄妭瀛楃
                 {
                     if (i + 3 >= data.Length) return false;
                     if ((data[i + 1] & 0xC0) != 0x80 || (data[i + 2] & 0xC0) != 0x80 || (data[i + 3] & 0xC0) != 0x80) return false;
@@ -171,5 +265,67 @@
             }
             return true;
         }
+
+        /// <summary>
+        /// 鎺ユ敹瀹屾暣娑堟伅锛堝抚瑙f瀽锛�
+        /// </summary>
+        /// <remarks>
+        /// 鏍规嵁閰嶇疆鐨勫ご灏炬爣璇嗚В鏋愭秷鎭��
+        /// 濡傛灉鏈厤缃ご灏撅紝鍒欎竴鐩磋鍒版暟鎹笉鍙敤銆�
+        /// </remarks>
+        /// <param name="networkStream">缃戠粶娴�</param>
+        /// <param name="encoding">瀛楃缂栫爜</param>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <returns>鎺ユ敹鍒扮殑娑堟伅</returns>
+        private async Task<string?> ReceiveFullMessageAsync(NetworkStream networkStream, Encoding encoding, CancellationToken cancellationToken)
+        {
+            var header = _options.MessageHeader ?? string.Empty;
+            var footer = _options.MessageFooter ?? string.Empty;
+
+            var buffer = new byte[1024];
+            var builder = new StringBuilder();
+
+            while (true)
+            {
+                // 璇诲彇鏁版嵁
+                int bytesRead = await networkStream.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken);
+                if (bytesRead <= 0)
+                {
+                    if (builder.Length == 0) return null;
+                    // 鏃犲ご灏鹃厤缃椂锛岃繑鍥炲凡鏈夋暟鎹�
+                    return string.IsNullOrEmpty(header) && string.IsNullOrEmpty(footer) ? builder.ToString() : null;
+                }
+
+                builder.Append(encoding.GetString(buffer, 0, bytesRead));
+
+                // 濡傛灉娌℃湁閰嶇疆澶村熬锛屼笖鏁版嵁涓嶅彲鐢紝杩斿洖宸叉湁鏁版嵁
+                if (string.IsNullOrEmpty(header) && string.IsNullOrEmpty(footer))
+                {
+                    if (!networkStream.DataAvailable)
+                    {
+                        break;
+                    }
+                    continue;
+                }
+
+                // 鏌ユ壘甯уご
+                var data = builder.ToString();
+                var headerIndex = string.IsNullOrEmpty(header) ? 0 : data.IndexOf(header, StringComparison.Ordinal);
+                if (headerIndex < 0)
+                {
+                    continue;
+                }
+
+                // 鎻愬彇甯у唴瀹�
+                var startIndex = headerIndex + header.Length;
+                var footerIndex = string.IsNullOrEmpty(footer) ? data.Length : data.IndexOf(footer, startIndex, StringComparison.Ordinal);
+                if (footerIndex >= 0)
+                {
+                    return data.Substring(startIndex, footerIndex - startIndex);
+                }
+            }
+
+            return builder.ToString();
+        }
     }
-}
\ No newline at end of file
+}

--
Gitblit v1.9.3