From 35507872814beed931cdf4b055355a6208a79900 Mon Sep 17 00:00:00 2001
From: root <295172551@qq.com>
Date: Wed, 23 Jul 2025 23:44:30 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96ILogger=E4=BD=BF=E7=94=A8?=
=?UTF-8?q?=E5=92=8C=E7=BB=84=E4=BB=B6=E4=BE=9D=E8=B5=96=E5=85=B3=E7=B3=BB?=
=?UTF-8?q?=20-=20=E4=B8=BAUeIdentifierManager=E5=92=8CProtocolLogContext?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0ILogger=E6=94=AF=E6=8C=81=20-=20=E5=B0=86ILog?=
=?UTF-8?q?ger=E5=8F=82=E6=95=B0=E6=94=B9=E4=B8=BA=E5=BF=85=E5=A1=AB?=
=?UTF-8?q?=EF=BC=8C=E6=8F=90=E9=AB=98=E4=BB=A3=E7=A0=81=E5=81=A5=E5=A3=AE?=
=?UTF-8?q?=E6=80=A7=20-=20=E4=B8=BAProtocolClientContext=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0ILoggerFactory=E6=94=AF=E6=8C=81=20-=20=E4=BC=98?=
=?UTF-8?q?=E5=8C=96ProtocolLogContext=E7=9A=84=E7=BB=84=E4=BB=B6=E9=97=B4?=
=?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E9=80=9A=E8=BF=87=E4=B8=8A=E4=B8=8B?=
=?UTF-8?q?=E6=96=87=E8=AE=BF=E9=97=AE=E5=85=84=E5=BC=9F=E7=BB=84=E4=BB=B6?=
=?UTF-8?q?=20-=20=E7=AE=80=E5=8C=96=E6=96=B9=E6=B3=95=E7=AD=BE=E5=90=8D?=
=?UTF-8?q?=EF=BC=8C=E7=A7=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84?=
=?UTF-8?q?=E5=8F=82=E6=95=B0=E4=BC=A0=E9=80=92=20-=20=E7=BB=9F=E4=B8=80?=
=?UTF-8?q?=E6=97=A5=E5=BF=97=E7=AE=A1=E7=90=86=EF=BC=8C=E9=81=B5=E5=BE=AA?=
=?UTF-8?q?Microsoft.Extensions.Logging=E6=9C=80=E4=BD=B3=E5=AE=9E?=
=?UTF-8?q?=E8=B7=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Context/CellParameterManager.cs | 118 ++
.../Context/ProtocolBasicInfo.cs | 20 +
.../Context/ProtocolClientContext.cs | 40 +
.../Context/ProtocolFeatureFlags.cs | 22 +
.../Context/ProtocolLogContext.cs | 80 ++
.../Context/ProtocolLogPatterns.cs | 71 ++
.../Context/UeStateManager/ProtocolParsing.cs | 154 +++
.../UeStateManager/StringIdManagement.cs | 138 ++
.../Context/UeStateManager/TmsiMatching.cs | 261 ++++
.../UeStateManager/UeIdentifierException.cs | 126 ++
.../UeStateManager/UeIdentifierManager.cs | 205 +++
.../UeStateManager/UeIdentifierMapping.cs | 271 ++++
.../UeStateManager/UeInfoManagement.cs | 244 ++++
.../CoreAgent.ProtocolClient.csproj | 4 -
.../Docs/MessageIdManager.md | 509 ++++++++
CoreAgent.ProtocolClient/Enums/TmsiType.cs | 29 +
.../Managers/MessageIdManager.cs | 61 +-
.../Managers/WebSocketMgr/Constructor.cs | 40 +-
.../Managers/WebSocketMgr/Dispose.cs | 51 +-
.../Managers/WebSocketMgr/PrivateMethods.cs | 203 +--
.../Managers/WebSocketMgr/PublicMethods.cs | 283 +----
.../WebSocketMgr/WebSocketMessageManager.cs | 408 +-----
.../{ProtocolLog.cs => BuildProtocolLog.cs} | 25 +-
...rotocolLogJson.cs => SourceProtocolLog.cs} | 26 +-
.../Models/TmsiMatchProcessor.cs | 14 +-
.../Models/TmsiMatchResult.cs | 63 +-
...colLogDetail.cs => TransferProtocolLog.cs} | 6 +-
CoreAgent.ProtocolClient/Models/UeInfo.cs | 2 +-
CoreAgent.ProtocolClient/modify.md | 1127 ++++++++++++++++-
29 files changed, 3602 insertions(+), 999 deletions(-)
create mode 100644 CoreAgent.ProtocolClient/Context/CellParameterManager.cs
create mode 100644 CoreAgent.ProtocolClient/Context/ProtocolBasicInfo.cs
create mode 100644 CoreAgent.ProtocolClient/Context/ProtocolClientContext.cs
create mode 100644 CoreAgent.ProtocolClient/Context/ProtocolFeatureFlags.cs
create mode 100644 CoreAgent.ProtocolClient/Context/ProtocolLogContext.cs
create mode 100644 CoreAgent.ProtocolClient/Context/ProtocolLogPatterns.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/ProtocolParsing.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/StringIdManagement.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/TmsiMatching.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierException.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierManager.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierMapping.cs
create mode 100644 CoreAgent.ProtocolClient/Context/UeStateManager/UeInfoManagement.cs
create mode 100644 CoreAgent.ProtocolClient/Docs/MessageIdManager.md
create mode 100644 CoreAgent.ProtocolClient/Enums/TmsiType.cs
rename CoreAgent.ProtocolClient/Models/{ProtocolLog.cs => BuildProtocolLog.cs} (89%)
rename CoreAgent.ProtocolClient/Models/{ProtocolLogJson.cs => SourceProtocolLog.cs} (82%)
rename CoreAgent.ProtocolClient/Models/{ProtocolLogDetail.cs => TransferProtocolLog.cs} (95%)
diff --git a/CoreAgent.ProtocolClient/Context/CellParameterManager.cs b/CoreAgent.ProtocolClient/Context/CellParameterManager.cs
new file mode 100644
index 0000000..cc9cff5
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/CellParameterManager.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Models;
+using Newtonsoft.Json;
+
+namespace CoreAgent.ProtocolClient.Context
+{
+ ///
+ /// 参数管理
+ ///
+ public class CellParameterManager
+ {
+ public Dictionary Parameters { get; set; } = new();
+ public List RanIds { get; set; } = new();
+
+ public void SetRanId(string ranId)
+ {
+ RanIds.Add(ranId);
+ }
+
+ public void AddCell(int id, CellConfig config)
+ {
+ if (Parameters.ContainsKey(id))
+ {
+ Parameters[id] = config;
+ }
+ else
+ {
+ Parameters.Add(id, config);
+ }
+ }
+
+ public void SetHeaders(string[] headers, ProtocolBasicInfo basicInfo)
+ {
+ basicInfo.Headers = headers;
+ var cells = new List>();
+ for (int i = 0; i < headers.Length; i++)
+ {
+ var header = headers[i];
+ Match? info;
+ info = Regex.Match(header, @"lte(\w+) version ([\d-]+)", RegexOptions.IgnoreCase);
+ if (info.Success)
+ {
+ basicInfo.Model = info.Groups[1].Value.ToUpper();
+ basicInfo.Version = info.Groups[2].Value;
+ }
+ else if (Regex.IsMatch(header, @"Licensed to"))
+ {
+ basicInfo.License = header;
+ }
+ else if ((info = Regex.Match(header, @"Metadata:(.+)$")).Success)
+ {
+ var metadata = JsonConvert.DeserializeObject>(info.Groups[1].Value);
+ }
+ else if ((info = Regex.Match(header, @"(global_(ran_node|enb)_id)=([\d\.]+)")).Success)
+ {
+ this.SetRanId(info.Groups[3].Value);
+ }
+ else if ((info = Regex.Match(header, @"Cell 0x(\d+): (.*)")).Success)
+ {
+ var cell = new Dictionary
+ {
+ ["cell_id"] = int.Parse(info.Groups[1].Value, System.Globalization.NumberStyles.HexNumber),
+ ["sib1Decoded"] = true,
+ ["sib2Decoded"] = true
+ };
+ var list = info.Groups[2].Value.Split(' ');
+ foreach (var param in list)
+ {
+ var parts = param.Split('=');
+ if (parts.Length == 2)
+ {
+ cell[parts[0]] = HeaderCellParam(parts[0], parts[1]);
+ }
+ }
+ cells.Add(cell);
+ }
+ else if (cells.Count > 0)
+ {
+ info = Regex.Match(header, @"([UD]L): (.*)");
+ if (info.Success)
+ {
+ var cell = cells[cells.Count - 1];
+ var dir = info.Groups[1].Value;
+ var list = info.Groups[2].Value.Split(' ');
+ foreach (var param in list)
+ {
+ var parts = param.Split('=');
+ if (parts.Length == 2)
+ {
+ cell[parts[0]] = HeaderCellParam(parts[0], parts[1]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private object HeaderCellParam(string param, string value)
+ {
+ switch (param)
+ {
+ case "br_dl_sf_bitmap":
+ case "nb_dl_sf_bitmap":
+ case "label":
+ return value;
+ default:
+ if (int.TryParse(value, out var intValue))
+ return intValue;
+ return value;
+ }
+ }
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/ProtocolBasicInfo.cs b/CoreAgent.ProtocolClient/Context/ProtocolBasicInfo.cs
new file mode 100644
index 0000000..a42ed07
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/ProtocolBasicInfo.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CoreAgent.ProtocolClient.Context
+{
+ ///
+ /// 基础信息
+ ///
+ public class ProtocolBasicInfo
+ {
+ public string? Name { get; set; }
+ public string? Version { get; set; }
+ public string? License { get; set; }
+ public string? Model { get; set; }
+ public string[]? Headers { get; set; }
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/ProtocolClientContext.cs b/CoreAgent.ProtocolClient/Context/ProtocolClientContext.cs
new file mode 100644
index 0000000..a8974d0
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/ProtocolClientContext.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Context.UeStateManager;
+using CoreAgent.ProtocolClient.Enums;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context
+{
+ public class ProtocolClientContext
+ {
+ // 常量和正则表达式已迁移至 ProtocolLogPatterns 静态类,便于统一管理和调用。
+
+ private readonly ILoggerFactory _loggerFactory;
+
+ public ProtocolBasicInfo BasicInfo { get; set; } = new();
+ public ProtocolFeatureFlags FeatureFlags { get; set; } = new();
+ public ProtocolLogContext LogContext { get; set; }
+ public UeIdentifierManager UeIdentifier { get; set; }
+ public CellParameterManager CellParameterManager { get; set; } = new();
+ public ClientState State { get; set; } = ClientState.Stop;
+
+ public ProtocolClientContext(ILoggerFactory loggerFactory)
+ {
+ _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
+
+ // 使用ILoggerFactory为各个组件创建正确的Logger
+ var ueIdentifierLogger = _loggerFactory.CreateLogger();
+ var logContextLogger = _loggerFactory.CreateLogger();
+
+ // 先创建UeIdentifierManager
+ UeIdentifier = new UeIdentifierManager(ueIdentifierLogger);
+
+ // 然后创建ProtocolLogContext,传入this引用
+ LogContext = new ProtocolLogContext(logContextLogger, this);
+ }
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/ProtocolFeatureFlags.cs b/CoreAgent.ProtocolClient/Context/ProtocolFeatureFlags.cs
new file mode 100644
index 0000000..975ab72
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/ProtocolFeatureFlags.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CoreAgent.ProtocolClient.Context
+{
+ ///
+ /// 功能标志
+ ///
+ public class ProtocolFeatureFlags
+ {
+ public bool HasCell { get; set; }
+ public bool HasPhy { get; set; }
+ public bool HasData { get; set; }
+ public bool HasRnti { get; set; }
+ public bool HasRb { get; set; }
+ public bool HasSignalRecord { get; set; }
+ public bool IsFirstGetLogs { get; set; } = true;
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/ProtocolLogContext.cs b/CoreAgent.ProtocolClient/Context/ProtocolLogContext.cs
new file mode 100644
index 0000000..1019458
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/ProtocolLogContext.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Context.UeStateManager;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context
+{
+ ///
+ /// 日志相关
+ ///
+ public class ProtocolLogContext
+ {
+ private static int _logIdCounter;
+ private readonly ILogger _logger;
+ private readonly ProtocolClientContext _context;
+
+ public List Logs { get; set; } = new();
+ public int LogCount => Logs.Count;
+
+ public ProtocolLogContext(ILogger logger, ProtocolClientContext context)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _context = context ?? throw new ArgumentNullException(nameof(context));
+ }
+ public void ResetLogs()
+ {
+ if (LogCount > 0)
+ {
+ Logs.Clear();
+ _context.FeatureFlags.HasCell = false;
+ _context.FeatureFlags.HasPhy = false;
+ _context.FeatureFlags.HasData = false;
+ _context.FeatureFlags.HasRnti = false;
+ _context.FeatureFlags.HasRb = false;
+ _context.FeatureFlags.HasSignalRecord = false;
+ }
+ }
+
+
+ ///
+ /// 更新日志的时间戳并分配唯一ID。
+ /// 检查并处理时间戳回绕,详细记录回绕前后各关键字段,包括:
+ /// 1. 原始日志时间戳(log.Timestamp)
+ /// 2. 当前偏移量(parser.TimestampOffset)
+ /// 3. 计算得到的当前时间戳(timestamp)
+ /// 4. 上次处理的时间戳(parser.LastTimestamp)
+ /// 5. 回绕后新的时间戳(timestamp + 86400000)
+ /// 6. 本次回绕的增量(86400000)
+ /// 7. 日志分配的唯一ID(log.Id)
+ ///
+ public void UpdateLogTimestampAndAssignId(ref BuildProtocolLog log)
+ {
+ // 检查时间戳回绕
+ var parser = _context.UeIdentifier;
+ var timestamp = log.Timestamp + parser.TimestampOffset;
+ if (timestamp < parser.LastTimestamp - 100)
+ {
+ _logger.LogInformation($"[Log回绕] 原始时间戳: {log.Timestamp}, 偏移量: {parser.TimestampOffset}, 回绕前: {timestamp}, parser.LastTimestamp(回绕前): {parser.LastTimestamp}, 回绕后: {timestamp + 86400000}, parser.LastTimestamp(回绕后): {parser.LastTimestamp}, 增量: 86400000, 日志ID(回绕前): {log.Id}");
+ timestamp += 86400000; // 24小时
+ parser.TimestampOffset += 86400000;
+ _logger.LogInformation($"[Log回绕后] 新时间戳: {timestamp}, parser.LastTimestamp(回绕后): {parser.LastTimestamp}, 新偏移量: {parser.TimestampOffset}, 日志ID(回绕后): {log.Id}");
+ }
+ var lastTimestampBefore = parser.LastTimestamp;
+ parser.LastTimestamp = log.Timestamp = timestamp;
+ log.Id = GenerateLogId();
+ _logger.LogDebug($"[Log分配ID] 日志最终时间戳: {log.Timestamp}, 分配ID: {log.Id}, 当前偏移量: {parser.TimestampOffset}, parser.LastTimestamp(分配前): {lastTimestampBefore}, parser.LastTimestamp(分配后): {parser.LastTimestamp}");
+ }
+
+
+ private static int GenerateLogId()
+ {
+ return Interlocked.Increment(ref _logIdCounter);
+ }
+
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/ProtocolLogPatterns.cs b/CoreAgent.ProtocolClient/Context/ProtocolLogPatterns.cs
new file mode 100644
index 0000000..4ffaf4c
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/ProtocolLogPatterns.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace CoreAgent.ProtocolClient.Context
+{
+ ///
+ /// 协议日志相关常量与正则表达式,便于全局统一管理和调用。
+ ///
+ public static class ProtocolLogPatterns
+ {
+ #region 常量定义
+
+ ///
+ /// HFN回绕阈值
+ ///
+ public const int HFN_WRAP_THRESHOLD = 512;
+
+ ///
+ /// 最大日志数量
+ ///
+ public const int LOGS_MAX = 2000000;
+
+ ///
+ /// BSR表 - 对应JavaScript中的_bsr_table
+ ///
+ public static readonly int[] BsrTable = {
+ 0, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4677, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000, 500000
+ };
+
+ #endregion
+
+ #region 正则表达式
+
+ public static readonly Regex RegExpPhy = new(@"^([a-f0-9\-]+)\s+([a-f0-9\-]+)\s+([\d\.\-]+) (\w+): (.+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpInfo1 = new(@"^([\w\-]+): (.+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpInfo2 = new(@"^([\w]+) (.+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpIP = new(@"^(len=\d+)\s+(\S+)\s+(.*)", RegexOptions.Compiled);
+ public static readonly Regex RegExpIPsec = new(@"^len=(\d+)\s+(.*)", RegexOptions.Compiled);
+ public static readonly Regex RegExpSDULen = new(@"SDU_len=(\d+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpSIP = new(@"^([:\.\[\]\da-f]+)\s+(\S+) (.+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpMediaReq = new(@"^(\S+) (.+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpSignalRecord = new(@"Link:\s([\w\d]+)@(\d+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpCellID = new(@"^([a-f0-9\-]+) (.+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpRRC_UE_ID = new(@"Changing UE_ID to 0x(\d+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpRRC_TMSI = new(@"(5G|m)-TMSI '([\dA-F]+)'H", RegexOptions.Compiled);
+ public static readonly Regex RegExpRRC_NEW_ID = new(@"newUE-Identity (['\dA-FH]+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpRRC_CRNTI = new(@"c-RNTI '([\dA-F]+)'H", RegexOptions.Compiled);
+ public static readonly Regex RegExpNAS_TMSI = new(@"[Mm]-TMSI = 0x([\da-f]+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpNAS_5GTMSI = new(@"5G-TMSI = 0x([\da-f]+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpRRC_BC = new(@"(EUTRA|MRDC|NR|NRDC) band combinations", RegexOptions.Compiled);
+ public static readonly Regex RegExpPDCCH = new(@"^\s*(.+)=(\d+)$", RegexOptions.Compiled);
+ public static readonly Regex RegExpS1NGAP = new(@"^([\da-f\-]+)\s+([\da-f\-]+) (([^\s]+) .+)", RegexOptions.Compiled);
+ public static readonly Regex RegExpHexDump = new(@"^[\da-f]+:(\s+[\da-f]{2}){1,16}\s+.{1,16}$", RegexOptions.Compiled);
+ public static readonly Regex RegMccPattern = new Regex(@"MCC\s*=\s*(\d+)", RegexOptions.Compiled);
+ public static readonly Regex RegMncPattern = new Regex(@"MNC\s*=\s*(\d+)", RegexOptions.Compiled);
+ public static readonly Regex RegMSINPattern = new Regex(@"MSIN\s*=\s*(\d+)", RegexOptions.Compiled);
+ public static readonly Regex RegIMSIPattern = new Regex(@"IMSI = \s*(\d+)", RegexOptions.Compiled);
+
+ public static Match? FindData(this Regex regex, List data)
+ {
+ return data?.FirstOrDefault(line => regex.IsMatch(line)) is string matchedLine
+ ? regex.Match(matchedLine)
+ : null;
+ }
+ #endregion
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/ProtocolParsing.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/ProtocolParsing.cs
new file mode 100644
index 0000000..e1a3b2b
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/ProtocolParsing.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Enums;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UeIdentifierManager 协议解析部分
+ ///
+ public partial class UeIdentifierManager
+ {
+ #region 协议解析方法
+
+ ///
+ /// 解析提示信息
+ ///
+ /// 协议日志
+ /// 解析配置
+ public void ParseHints(BuildProtocolLog log, Dictionary config)
+ {
+ if (log?.Info != (int)LogChannelId.ID_HINTS)
+ {
+ _logger?.LogDebug("跳过非提示信息日志: Info={Info}", log?.Info);
+ return;
+ }
+
+ try
+ {
+ var hints = ParseArguments(log.Message, config);
+ _logger?.LogDebug("解析提示信息成功,共解析 {Count} 个参数", hints.Count);
+ // TODO: 处理解析后的提示信息
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "解析提示信息失败: {Message}", log.Message);
+ throw new ParsingException("Hints", log?.Message ?? "", $"解析提示信息失败: {ex.Message}", ex);
+ }
+ }
+
+ ///
+ /// 解析参数字符串为字典
+ /// 性能优化:使用编译后的正则表达式
+ ///
+ /// 参数字符串,格式如 "a=1 b=2 c=hello"
+ ///
+ /// 配置字典,key为参数名,value为类型(Type)或处理函数(Func<string, object>)
+ /// 例如:{ "a", typeof(int) }, { "b", (Func<string, object>)(s => s.ToUpper()) }
+ ///
+ /// 解析后的参数字典
+ private Dictionary ParseArguments(string arguments, Dictionary config)
+ {
+ if (string.IsNullOrEmpty(arguments))
+ {
+ return new Dictionary();
+ }
+
+ var result = new Dictionary();
+ // 使用编译后的正则表达式提高性能
+ var whitespaceRegex = new Regex(@"\s+", RegexOptions.Compiled);
+
+ try
+ {
+ foreach (var argument in whitespaceRegex.Split(arguments))
+ {
+ if (string.IsNullOrWhiteSpace(argument))
+ continue;
+
+ var keyValuePair = argument.Split('=', 2);
+ if (keyValuePair.Length != 2)
+ {
+ _logger?.LogWarning("跳过格式无效的参数: {Argument}", argument);
+ continue;
+ }
+
+ var key = keyValuePair[0];
+ var value = keyValuePair[1];
+
+ result[key] = ParseValue(value, key, config);
+ }
+
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "解析参数字符串失败: {Arguments}", arguments);
+ throw new ParsingException("Arguments", arguments, $"解析参数字符串失败: {ex.Message}", ex);
+ }
+ }
+
+ ///
+ /// 根据配置解析参数值
+ ///
+ /// 原始值字符串
+ /// 参数键
+ /// 解析配置
+ /// 解析后的值
+ private object ParseValue(string value, string key, Dictionary config)
+ {
+ if (!config.TryGetValue(key, out var typeOrFunc))
+ return value;
+
+ try
+ {
+ return typeOrFunc switch
+ {
+ Type type when type == typeof(int) => int.TryParse(value, out var intValue) ? intValue : 0,
+ Type type when type == typeof(double) => double.TryParse(value, out var doubleValue) ? doubleValue : 0.0,
+ Func func => func(value),
+ _ => value
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "解析参数值失败: Key={Key}, Value={Value}", key, value);
+ return value; // 返回原始值作为回退
+ }
+ }
+
+ ///
+ /// 批量解析参数
+ /// 性能优化:批量处理减少重复计算
+ ///
+ /// 参数字符串列表
+ /// 解析配置
+ /// 解析结果列表
+ public List> ParseArgumentsBatch(
+ IEnumerable argumentsList,
+ Dictionary config)
+ {
+ if (argumentsList == null)
+ {
+ throw new ArgumentNullException(nameof(argumentsList));
+ }
+
+ var results = new List>();
+ foreach (var arguments in argumentsList)
+ {
+ results.Add(ParseArguments(arguments, config));
+ }
+
+ _logger?.LogDebug("批量解析参数完成,共处理 {Count} 个参数字符串", results.Count);
+ return results;
+ }
+
+ #endregion
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/StringIdManagement.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/StringIdManagement.cs
new file mode 100644
index 0000000..de4d9e4
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/StringIdManagement.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UeIdentifierManager 字符串ID管理部分
+ ///
+ public partial class UeIdentifierManager
+ {
+ #region 字符串ID管理方法
+
+ ///
+ /// 将字符串转换为ID,如果不存在则创建新的ID
+ /// 性能优化:使用缓存减少重复计算
+ ///
+ /// 要转换的字符串
+ /// 对应的ID
+ /// 字符串为空时抛出
+ public int StringToId(string str)
+ {
+ if (string.IsNullOrEmpty(str))
+ {
+ _logger?.LogWarning("尝试转换空字符串为ID");
+ return 0;
+ }
+
+ lock (_lockObject)
+ {
+ IncrementCacheStat("StringToId");
+
+ if (_stringIdCache.TryGetValue(str, out int existingId))
+ {
+ IncrementCacheStat("CacheHits");
+ return existingId;
+ }
+
+ IncrementCacheStat("CacheMisses");
+ int newId = _stringList.Count + 1;
+ _stringIdCache[str] = newId;
+ _stringList.Add(str);
+
+ _logger?.LogDebug("创建新的字符串ID映射: '{String}' -> {Id}", str, newId);
+ return newId;
+ }
+ }
+
+ ///
+ /// 根据ID获取对应的字符串
+ /// 性能优化:使用缓存减少重复计算
+ ///
+ /// 字符串ID
+ /// 对应的字符串,如果ID无效则返回空字符串
+ public string IdToString(int id)
+ {
+ if (id <= 0)
+ {
+ _logger?.LogWarning("尝试获取无效ID的字符串: {Id}", id);
+ return string.Empty;
+ }
+
+ lock (_lockObject)
+ {
+ IncrementCacheStat("IdToString");
+
+ if (id <= _stringList.Count)
+ {
+ IncrementCacheStat("CacheHits");
+ return _stringList[id - 1];
+ }
+
+ IncrementCacheStat("CacheMisses");
+ _logger?.LogWarning("ID超出范围: {Id}, 最大ID: {MaxId}", id, _stringList.Count);
+ return string.Empty;
+ }
+ }
+
+ ///
+ /// 批量转换字符串为ID
+ /// 性能优化:批量处理减少锁开销
+ ///
+ /// 字符串列表
+ /// 对应的ID列表
+ public List StringToIdBatch(IEnumerable strings)
+ {
+ if (strings == null)
+ {
+ throw new ArgumentNullException(nameof(strings));
+ }
+
+ var results = new List();
+ lock (_lockObject)
+ {
+ foreach (var str in strings)
+ {
+ results.Add(StringToId(str));
+ }
+ }
+
+ _logger?.LogDebug("批量转换字符串为ID,共处理 {Count} 个字符串", results.Count);
+ return results;
+ }
+
+ ///
+ /// 获取字符串缓存信息
+ ///
+ /// 缓存信息
+ public (int CacheSize, int ListSize) GetStringCacheInfo()
+ {
+ lock (_lockObject)
+ {
+ return (_stringIdCache.Count, _stringList.Count);
+ }
+ }
+
+ #endregion
+
+ #region 私有辅助方法
+
+ ///
+ /// 增加缓存统计计数
+ ///
+ /// 统计名称
+ private void IncrementCacheStat(string statName)
+ {
+ if (_cacheStats.ContainsKey(statName))
+ {
+ _cacheStats[statName]++;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/TmsiMatching.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/TmsiMatching.cs
new file mode 100644
index 0000000..53fc378
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/TmsiMatching.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UeIdentifierManager TMSI匹配部分
+ ///
+ public partial class UeIdentifierManager
+ {
+ #region TMSI匹配方法
+
+ ///
+ /// 根据TMSI匹配生成请求UE ID和接收UE ID的对应关系
+ /// 使用TmsiMatchProcessor处理匹配逻辑
+ ///
+ /// TMSI匹配结果列表
+ public List GenerateTmsiMatches()
+ {
+ try
+ {
+ var processor = new TmsiMatchProcessor(TmsiToUeId, RequestTmsiToUeId, ImsiToUeId);
+ var results = processor.GenerateTmsiMatches();
+ _logger?.LogDebug("生成TMSI匹配结果,共 {Count} 个匹配", results.Count);
+ return results;
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "生成TMSI匹配失败");
+ throw new GeneralUeIdentifierManagerException("GenerateTmsiMatches", "生成TMSI匹配失败", ex);
+ }
+ }
+
+ ///
+ /// 根据UE ID获取对应的IMSI
+ /// 优先查找当前UE ID,如果未找到则查找整个UE链中的IMSI
+ ///
+ /// UE ID
+ /// 对应的IMSI,如果未找到则返回空字符串
+ private string GetImsiForUeId(int ueId)
+ {
+ if (ueId <= 0)
+ {
+ _logger?.LogWarning("尝试获取无效UE ID的IMSI: {UeId}", ueId);
+ return string.Empty;
+ }
+
+ try
+ {
+ // 1. 首先查找当前UE ID对应的IMSI
+ var currentImsiMapping = ImsiToUeId.FirstOrDefault(kvp => kvp.Value.Contains(ueId));
+ if (!string.IsNullOrEmpty(currentImsiMapping.Key))
+ {
+ return currentImsiMapping.Key;
+ }
+
+ // 2. 如果当前UE ID没有IMSI,查找整个UE链中的IMSI
+ var anyImsiMapping = ImsiToUeId.FirstOrDefault(kvp => !string.IsNullOrEmpty(kvp.Key));
+ return anyImsiMapping.Key ?? string.Empty;
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "获取UE {UeId} 的IMSI失败", ueId);
+ return string.Empty;
+ }
+ }
+
+ ///
+ /// 获取UE链的统计信息
+ ///
+ /// UE链统计信息
+ public UeChainStats GetUeChainStats()
+ {
+ try
+ {
+ var processor = new TmsiMatchProcessor(TmsiToUeId, RequestTmsiToUeId, ImsiToUeId);
+ var stats = processor.GetUeChainStats();
+ _logger?.LogDebug("获取UE链统计信息成功");
+ return stats;
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "获取UE链统计信息失败");
+ throw new GeneralUeIdentifierManagerException("GetUeChainStats", "获取UE链统计信息失败", ex);
+ }
+ }
+
+ ///
+ /// 获取所有UE链的详细信息
+ ///
+ /// UE链详细信息列表
+ public List GetUeChainDetails()
+ {
+ try
+ {
+ var processor = new TmsiMatchProcessor(TmsiToUeId, RequestTmsiToUeId, ImsiToUeId);
+ var details = processor.GetUeChainDetails();
+ _logger?.LogDebug("获取UE链详细信息成功,共 {Count} 个链", details.Count);
+ return details;
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "获取UE链详细信息失败");
+ throw new GeneralUeIdentifierManagerException("GetUeChainDetails", "获取UE链详细信息失败", ex);
+ }
+ }
+
+ ///
+ /// 将 SrTmsiToUeId 平铺成 SrTmsiMapping 列表,并与 GenerateTmsiMatches 结果匹配更新 IMSI、Root UE ID 和 PLMN
+ /// 性能优化:使用LINQ提高查找效率
+ ///
+ /// 平铺后的 SrTmsiMapping 列表,包含匹配的 IMSI、Root UE ID 和 PLMN 信息
+ public List GenerateSrTmsiMappings(List tmsiMatches)
+ {
+ if (tmsiMatches == null)
+ {
+ throw new ArgumentNullException(nameof(tmsiMatches));
+ }
+
+ try
+ {
+ var srTmsiMappings = new List();
+
+ // 1. 平铺 SrTmsiToUeId 字典数据
+ foreach (var kvp in SrTmsiToUeId)
+ {
+ uint tmsi = kvp.Key;
+ var ueIds = kvp.Value;
+
+ foreach (int ueId in ueIds)
+ {
+ var mapping = new SrTmsiMapping(string.Empty, tmsi, ueId);
+ srTmsiMappings.Add(mapping);
+ }
+ }
+
+ // 2. 获取 UE 链信息以获取最外层的 Root UE ID
+ var ueChainDetails = GetUeChainDetails();
+
+ // 3. 根据 TMSI 匹配结果更新 SrTmsiMapping 的 IMSI 和 Root UE ID
+ foreach (var srMapping in srTmsiMappings)
+ {
+ UpdateSrTmsiMapping(srMapping, tmsiMatches, ueChainDetails);
+ }
+
+ // 4. 根据 RootUeId 从 PlmnToUeId 映射表更新 PLMN 信息
+ foreach (var srMapping in srTmsiMappings)
+ {
+ UpdateSrTmsiMappingPlmn(srMapping, ueChainDetails);
+ }
+
+ _logger?.LogDebug("生成Service Request TMSI映射成功,共 {Count} 个映射", srTmsiMappings.Count);
+ return srTmsiMappings;
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "生成Service Request TMSI映射失败");
+ throw new GeneralUeIdentifierManagerException("GenerateSrTmsiMappings", "生成Service Request TMSI映射失败", ex);
+ }
+ }
+
+ #endregion
+
+ #region 私有辅助方法
+
+ ///
+ /// 更新 SrTmsiMapping 的 IMSI 和 Root UE ID
+ ///
+ /// Service Request TMSI映射
+ /// TMSI匹配结果
+ /// UE链详细信息
+ private void UpdateSrTmsiMapping(SrTmsiMapping srMapping, List tmsiMatches, List ueChainDetails)
+ {
+ // 查找匹配的 TMSI 结果
+ var matchingResult = tmsiMatches.FirstOrDefault(match => match.Tmsi == srMapping.Tmsi);
+
+ if (matchingResult != null && !string.IsNullOrEmpty(matchingResult.Imsi))
+ {
+ // 更新 IMSI
+ srMapping.Imsi = matchingResult.Imsi;
+
+ // 查找对应的最外层 Root UE ID
+ var chainInfo = ueChainDetails.FirstOrDefault(chain =>
+ chain.UeIds.Contains(srMapping.UeId));
+
+ if (chainInfo != null)
+ {
+ srMapping.RootUeId = chainInfo.RootUeId;
+ }
+ else
+ {
+ // 如果当前 UE ID 不在任何链中,尝试从匹配结果中查找
+ chainInfo = ueChainDetails.FirstOrDefault(chain =>
+ chain.UeIds.Contains(matchingResult.RequestUeId) ||
+ chain.UeIds.Contains(matchingResult.ReceiveUeId));
+
+ if (chainInfo != null)
+ {
+ srMapping.RootUeId = chainInfo.RootUeId;
+ }
+ }
+ }
+ else
+ {
+ // 如果 TMSI 匹配中没有找到,尝试从 ImsiToUeId 映射中查找
+ string imsi = GetImsiForUeId(srMapping.UeId);
+ if (!string.IsNullOrEmpty(imsi))
+ {
+ srMapping.Imsi = imsi;
+
+ // 查找对应的最外层 Root UE ID
+ var chainInfo = ueChainDetails.FirstOrDefault(chain =>
+ chain.UeIds.Contains(srMapping.UeId));
+
+ if (chainInfo != null)
+ {
+ srMapping.RootUeId = chainInfo.RootUeId;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 更新 SrTmsiMapping 的 PLMN 信息
+ ///
+ /// Service Request TMSI映射
+ private void UpdateSrTmsiMappingPlmn(SrTmsiMapping srMapping, List ueChainDetails)
+ {
+ if (srMapping.RootUeId > 0)
+ {
+ // 查找包含 RootUeId 的 PLMN 映射
+ var plmnMapping = PlmnToUeId.FirstOrDefault(kvp => kvp.Value.Contains(srMapping.RootUeId));
+ if (!string.IsNullOrEmpty(plmnMapping.Key))
+ {
+ srMapping.Plmn = plmnMapping.Key;
+ }
+ }
+ else if (srMapping.UeId > 0)
+ {
+ var Filter = TmsiToUeId.FirstOrDefault(s => s.Key == srMapping.Tmsi);
+ // 如果 RootUeId 为空,尝试使用 UeId 查找 PLMN
+ var chainInfo = ueChainDetails.FirstOrDefault(chain =>
+ chain.UeIds.Contains(Filter.Value));
+
+ var plmnMapping = PlmnToUeId.FirstOrDefault(kvp => kvp.Value.Contains(Filter.Value));
+ if (!string.IsNullOrEmpty(plmnMapping.Key))
+ {
+ srMapping.Plmn = plmnMapping.Key;
+ srMapping.RootUeId = chainInfo.RootUeId;
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierException.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierException.cs
new file mode 100644
index 0000000..0eb4e9b
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierException.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UeIdentifierManager 相关异常基类
+ ///
+ public abstract class UeIdentifierManagerException : Exception
+ {
+ protected UeIdentifierManagerException(string message) : base(message) { }
+ protected UeIdentifierManagerException(string message, Exception innerException) : base(message, innerException) { }
+ }
+
+ ///
+ /// 标识符格式异常
+ ///
+ public class IdentifierFormatException : UeIdentifierManagerException
+ {
+ public string Identifier { get; }
+ public string ExpectedFormat { get; }
+
+ public IdentifierFormatException(string identifier, string expectedFormat, string message = null)
+ : base(message ?? $"标识符 '{identifier}' 格式无效,期望格式: {expectedFormat}")
+ {
+ Identifier = identifier;
+ ExpectedFormat = expectedFormat;
+ }
+ }
+
+ ///
+ /// UE信息异常
+ ///
+ public class UeInfoException : UeIdentifierManagerException
+ {
+ public int UeId { get; }
+
+ public UeInfoException(int ueId, string message)
+ : base(message)
+ {
+ UeId = ueId;
+ }
+ }
+
+ ///
+ /// 映射关系异常
+ ///
+ public class MappingException : UeIdentifierManagerException
+ {
+ public string MappingType { get; }
+ public object Key { get; }
+
+ public MappingException(string mappingType, object key, string message)
+ : base(message)
+ {
+ MappingType = mappingType;
+ Key = key;
+ }
+ }
+
+ ///
+ /// 缓存异常
+ ///
+ public class CacheException : UeIdentifierManagerException
+ {
+ public string CacheType { get; }
+
+ public CacheException(string cacheType, string message)
+ : base(message)
+ {
+ CacheType = cacheType;
+ }
+
+ public CacheException(string cacheType, string message, Exception innerException)
+ : base(message, innerException)
+ {
+ CacheType = cacheType;
+ }
+ }
+
+ ///
+ /// 解析异常
+ ///
+ public class ParsingException : UeIdentifierManagerException
+ {
+ public string ParsingType { get; }
+ public string Input { get; }
+
+ public ParsingException(string parsingType, string input, string message)
+ : base(message)
+ {
+ ParsingType = parsingType;
+ Input = input;
+ }
+
+ public ParsingException(string parsingType, string input, string message, Exception innerException)
+ : base(message, innerException)
+ {
+ ParsingType = parsingType;
+ Input = input;
+ }
+ }
+
+ ///
+ /// 通用UE标识符管理器异常
+ ///
+ public class GeneralUeIdentifierManagerException : UeIdentifierManagerException
+ {
+ public string Operation { get; }
+
+ public GeneralUeIdentifierManagerException(string operation, string message)
+ : base(message)
+ {
+ Operation = operation;
+ }
+
+ public GeneralUeIdentifierManagerException(string operation, string message, Exception innerException)
+ : base(message, innerException)
+ {
+ Operation = operation;
+ }
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierManager.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierManager.cs
new file mode 100644
index 0000000..bcb0db7
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierManager.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Enums;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UE标识符管理类
+ /// 负责管理UE信息、标识符映射、时间戳等状态
+ /// 优化版本:增强异常处理、性能优化、代码拆分
+ ///
+ public partial class UeIdentifierManager
+ {
+ #region 公共属性 - 映射表
+
+ ///
+ /// TMSI到UE ID的映射表
+ ///
+ public Dictionary TmsiToUeId { get; set; } = new();
+
+ ///
+ /// 请求TMSI到UE ID的映射表
+ ///
+ public Dictionary RequestTmsiToUeId { get; set; } = new();
+
+ ///
+ /// IMSI到UE ID的映射表
+ ///
+ public Dictionary> ImsiToUeId { get; set; } = new();
+
+ ///
+ /// PLMN到UE ID的映射表
+ ///
+ public Dictionary> PlmnToUeId { get; set; } = new();
+
+ ///
+ /// Service Request TMSI到UE ID的映射表
+ ///
+ public Dictionary> SrTmsiToUeId { get; set; } = new();
+
+ ///
+ /// RNTI到UE ID的映射表
+ ///
+ public Dictionary RntiToUeId { get; set; } = new();
+
+ ///
+ /// UE信息列表,以UE ID为键
+ ///
+ public Dictionary UeList { get; set; } = new();
+
+ #endregion
+
+ #region 公共属性 - 时间戳和小区信息
+
+ ///
+ /// 最后处理的时间戳
+ ///
+ public long LastTimestamp { get; set; }
+
+ ///
+ /// 时间戳偏移量
+ ///
+ public long TimestampOffset { get; set; }
+
+ ///
+ /// 最后处理的小区ID
+ ///
+ public int? LastCell { get; set; }
+
+ #endregion
+
+ #region 私有字段 - 字符串缓存和性能优化
+
+ ///
+ /// 字符串到ID的映射缓存
+ ///
+ private readonly Dictionary _stringIdCache = new();
+
+ ///
+ /// ID到字符串的列表缓存
+ ///
+ private readonly List _stringList = new();
+
+ ///
+ /// 日志记录器
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// 缓存统计信息
+ ///
+ private readonly Dictionary _cacheStats = new();
+
+ ///
+ /// 线程锁对象
+ ///
+ private readonly object _lockObject = new object();
+
+ #endregion
+
+ #region 构造函数
+
+ ///
+ /// 初始化UE标识符管理器
+ ///
+ /// 日志记录器
+ public UeIdentifierManager(ILogger logger)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ InitializeProtocolTypeStrings();
+ InitializeCacheStats();
+ }
+
+ #endregion
+
+ #region 私有初始化方法
+
+ ///
+ /// 初始化协议类型字符串缓存
+ ///
+ private void InitializeProtocolTypeStrings()
+ {
+ try
+ {
+ string[] protocolTypeNames = Enum.GetNames(typeof(LogChannelId));
+ foreach (var protocolTypeName in protocolTypeNames)
+ {
+ StringToId(protocolTypeName);
+ }
+ _logger.LogDebug("协议类型字符串缓存初始化完成,共 {Count} 个类型", protocolTypeNames.Length);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "初始化协议类型字符串缓存失败");
+ throw new CacheException("ProtocolTypeStrings", "初始化协议类型字符串缓存失败", ex);
+ }
+ }
+
+ ///
+ /// 初始化缓存统计信息
+ ///
+ private void InitializeCacheStats()
+ {
+ _cacheStats["StringToId"] = 0;
+ _cacheStats["IdToString"] = 0;
+ _cacheStats["CacheHits"] = 0;
+ _cacheStats["CacheMisses"] = 0;
+ }
+
+ #endregion
+
+ #region 公共方法 - 统计和监控
+
+ ///
+ /// 获取缓存统计信息
+ ///
+ /// 缓存统计信息字典
+ public Dictionary GetCacheStats()
+ {
+ lock (_lockObject)
+ {
+ return new Dictionary(_cacheStats);
+ }
+ }
+
+ ///
+ /// 获取映射表统计信息
+ ///
+ /// 映射表统计信息
+ public Dictionary GetMappingStats()
+ {
+ return new Dictionary
+ {
+ ["TmsiToUeId"] = TmsiToUeId.Count,
+ ["RequestTmsiToUeId"] = RequestTmsiToUeId.Count,
+ ["ImsiToUeId"] = ImsiToUeId.Count,
+ ["PlmnToUeId"] = PlmnToUeId.Count,
+ ["SrTmsiToUeId"] = SrTmsiToUeId.Count,
+ ["RntiToUeId"] = RntiToUeId.Count,
+ ["UeList"] = UeList.Count
+ };
+ }
+
+ ///
+ /// 清理缓存
+ ///
+ public void ClearCache()
+ {
+ lock (_lockObject)
+ {
+ _stringIdCache.Clear();
+ _stringList.Clear();
+ InitializeCacheStats();
+ _logger.LogInformation("字符串缓存已清理");
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierMapping.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierMapping.cs
new file mode 100644
index 0000000..009d6e9
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/UeIdentifierMapping.cs
@@ -0,0 +1,271 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Enums;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UeIdentifierManager UE标识符映射部分
+ ///
+ public partial class UeIdentifierManager
+ {
+ #region UE标识符映射方法
+
+ ///
+ /// 设置IMSI与UE ID的映射关系
+ /// 性能优化:使用HashSet提高查找效率
+ ///
+ /// UE ID
+ /// IMSI标识符
+ /// UE ID无效时抛出
+ public void SetImsi(int ueId, string imsi)
+ {
+ if (string.IsNullOrEmpty(imsi))
+ {
+ _logger?.LogWarning("尝试设置空的IMSI");
+ return;
+ }
+
+ if (ueId <= 0)
+ {
+ throw new UeInfoException(ueId, "UE ID必须大于0");
+ }
+
+ try
+ {
+ lock (_lockObject)
+ {
+ if (!ImsiToUeId.TryGetValue(imsi, out var existingUeIds))
+ {
+ ImsiToUeId[imsi] = new List { ueId };
+ _logger?.LogDebug("创建新的IMSI映射: {Imsi} -> UE {UeId}", imsi, ueId);
+ }
+ else if (!existingUeIds.Contains(ueId))
+ {
+ existingUeIds.Add(ueId);
+ _logger?.LogDebug("添加IMSI映射: {Imsi} -> UE {UeId}", imsi, ueId);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "设置IMSI映射失败: UE {UeId}, IMSI {Imsi}", ueId, imsi);
+ throw new MappingException("IMSI", imsi, $"设置IMSI映射失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 设置TMSI与UE ID的映射关系
+ /// 性能优化:使用缓存减少重复转换
+ ///
+ /// UE ID
+ /// TMSI标识符(十六进制字符串)
+ /// TMSI格式无效时抛出
+ public void SetTmsi(int ueId, string tmsi)
+ {
+ if (string.IsNullOrEmpty(tmsi))
+ {
+ _logger?.LogWarning("尝试设置空的TMSI");
+ return;
+ }
+
+ if (ueId <= 0)
+ {
+ throw new UeInfoException(ueId, "UE ID必须大于0");
+ }
+
+ try
+ {
+ uint tmsiKey = Convert.ToUInt32(tmsi, 16);
+
+ lock (_lockObject)
+ {
+ if (TmsiToUeId.TryGetValue(tmsiKey, out int existingUeId) && existingUeId > 0)
+ {
+ // 同步IMSI信息
+ SyncImsiFromExistingUe(existingUeId, ueId);
+ // 合并UE信息
+ MergeUeInfo(existingUeId, ueId);
+ _logger?.LogDebug("更新TMSI映射: {Tmsi} -> UE {UeId} (原UE {ExistingUeId})", tmsi, ueId, existingUeId);
+ }
+ else
+ {
+ TmsiToUeId[tmsiKey] = ueId;
+ _logger?.LogDebug("创建新的TMSI映射: {Tmsi} -> UE {UeId}", tmsi, ueId);
+ }
+ }
+ }
+ catch (FormatException ex)
+ {
+ var errorMessage = $"TMSI格式无效: '{tmsi}',期望十六进制格式";
+ _logger?.LogError(ex, errorMessage);
+ throw new IdentifierFormatException(tmsi, "十六进制格式", errorMessage);
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "设置TMSI映射失败: UE {UeId}, TMSI {Tmsi}", ueId, tmsi);
+ throw new MappingException("TMSI", tmsi, $"设置TMSI映射失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 设置请求TMSI与UE ID的映射关系
+ ///
+ /// UE ID
+ /// 请求TMSI标识符(十六进制字符串)
+ public void SetRequestTmsi(int ueId, string tmsi)
+ {
+ if (string.IsNullOrEmpty(tmsi))
+ {
+ _logger?.LogWarning("尝试设置空的请求TMSI");
+ return;
+ }
+
+ if (ueId <= 0)
+ {
+ throw new UeInfoException(ueId, "UE ID必须大于0");
+ }
+
+ try
+ {
+ uint tmsiKey = Convert.ToUInt32(tmsi, 16);
+
+ lock (_lockObject)
+ {
+ RequestTmsiToUeId[tmsiKey] = ueId;
+ _logger?.LogDebug("设置请求TMSI映射: {Tmsi} -> UE {UeId}", tmsi, ueId);
+ }
+ }
+ catch (FormatException ex)
+ {
+ var errorMessage = $"请求TMSI格式无效: '{tmsi}',期望十六进制格式";
+ _logger?.LogError(ex, errorMessage);
+ throw new IdentifierFormatException(tmsi, "十六进制格式", errorMessage);
+ }
+ }
+
+ ///
+ /// 设置RNTI与UE ID的映射关系
+ ///
+ /// 协议日志
+ /// RNTI标识符(十六进制字符串)
+ public void SetRnti(BuildProtocolLog log, string rnti)
+ {
+ if (log?.UeId == null || string.IsNullOrEmpty(rnti))
+ {
+ _logger?.LogWarning("设置RNTI映射失败:日志或RNTI为空");
+ return;
+ }
+
+ try
+ {
+ int rntiId = int.Parse(rnti, System.Globalization.NumberStyles.HexNumber);
+
+ lock (_lockObject)
+ {
+ RntiToUeId[rntiId] = log.UeId.Value;
+ _logger?.LogDebug("设置RNTI映射: {Rnti} -> UE {UeId}", rnti, log.UeId.Value);
+ }
+ }
+ catch (FormatException ex)
+ {
+ var errorMessage = $"RNTI格式无效: '{rnti}',期望十六进制格式";
+ _logger?.LogError(ex, errorMessage);
+ throw new IdentifierFormatException(rnti, "十六进制格式", errorMessage);
+ }
+ }
+
+ ///
+ /// 设置PLMN与UE ID的映射关系
+ ///
+ /// UE ID
+ /// PLMN标识符
+ public void SetPlmn(int ueId, string plmn)
+ {
+ if (string.IsNullOrEmpty(plmn))
+ {
+ _logger?.LogWarning("尝试设置空的PLMN");
+ return;
+ }
+
+ if (ueId <= 0)
+ {
+ throw new UeInfoException(ueId, "UE ID必须大于0");
+ }
+
+ try
+ {
+ lock (_lockObject)
+ {
+ if (!PlmnToUeId.TryGetValue(plmn, out var existingUeIds))
+ {
+ PlmnToUeId[plmn] = new List { ueId };
+ _logger?.LogDebug("创建新的PLMN映射: {Plmn} -> UE {UeId}", plmn, ueId);
+ }
+ else if (!existingUeIds.Contains(ueId))
+ {
+ existingUeIds.Add(ueId);
+ _logger?.LogDebug("添加PLMN映射: {Plmn} -> UE {UeId}", plmn, ueId);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "设置PLMN映射失败: UE {UeId}, PLMN {Plmn}", ueId, plmn);
+ throw new MappingException("PLMN", plmn, $"设置PLMN映射失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 设置Service Request TMSI与UE ID的映射关系
+ ///
+ /// UE ID
+ /// Service Request TMSI标识符(十六进制字符串)
+ public void SetSrTmsi(int ueId, string srTmsi)
+ {
+ if (string.IsNullOrEmpty(srTmsi))
+ {
+ _logger?.LogWarning("尝试设置空的Service Request TMSI");
+ return;
+ }
+
+ if (ueId <= 0)
+ {
+ throw new UeInfoException(ueId, "UE ID必须大于0");
+ }
+
+ try
+ {
+ uint srTmsiKey = Convert.ToUInt32(srTmsi, 16);
+
+ lock (_lockObject)
+ {
+ if (!SrTmsiToUeId.TryGetValue(srTmsiKey, out var existingUeIds))
+ {
+ SrTmsiToUeId[srTmsiKey] = new List { ueId };
+ _logger?.LogDebug("创建新的Service Request TMSI映射: {SrTmsi} -> UE {UeId}", srTmsi, ueId);
+ }
+ else if (!existingUeIds.Contains(ueId))
+ {
+ existingUeIds.Add(ueId);
+ _logger?.LogDebug("添加Service Request TMSI映射: {SrTmsi} -> UE {UeId}", srTmsi, ueId);
+ }
+ }
+ }
+ catch (FormatException ex)
+ {
+ var errorMessage = $"Service Request TMSI格式无效: '{srTmsi}',期望十六进制格式";
+ _logger?.LogError(ex, errorMessage);
+ throw new IdentifierFormatException(srTmsi, "十六进制格式", errorMessage);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/CoreAgent.ProtocolClient/Context/UeStateManager/UeInfoManagement.cs b/CoreAgent.ProtocolClient/Context/UeStateManager/UeInfoManagement.cs
new file mode 100644
index 0000000..e9defb1
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Context/UeStateManager/UeInfoManagement.cs
@@ -0,0 +1,244 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+
+namespace CoreAgent.ProtocolClient.Context.UeStateManager
+{
+ ///
+ /// UeIdentifierManager UE信息管理部分
+ ///
+ public partial class UeIdentifierManager
+ {
+ #region UE信息管理方法
+
+ ///
+ /// 合并两个UE的信息
+ /// 性能优化:减少不必要的对象创建
+ ///
+ /// 第一个UE ID
+ /// 第二个UE ID
+ public void MergeUeInfo(int ueId1, int ueId2)
+ {
+ if (ueId1 <= 0 || ueId2 <= 0)
+ {
+ throw new UeInfoException(Math.Min(ueId1, ueId2), "UE ID必须大于0");
+ }
+
+ try
+ {
+ lock (_lockObject)
+ {
+ UeList.TryGetValue(ueId1, out var ue1);
+ UeList.TryGetValue(ueId2, out var ue2);
+
+ if (ReferenceEquals(ue1, ue2))
+ {
+ if (ue2 == null)
+ {
+ ue2 = CreateUeInfo(ueId2);
+ UeList[ueId1] = ue2;
+ }
+ }
+ else if (ue1 == null)
+ {
+ UeList[ueId1] = ue2;
+ }
+ else if (ue2 == null)
+ {
+ UeList[ueId2] = ue1;
+ SyncPlmnFromExistingUe(ueId1, ueId2);
+ }
+ else
+ {
+ UeList[ueId2] = ue1;
+ SyncPlmnFromExistingUe(ueId1, ueId2);
+ }
+
+ _logger?.LogDebug("合并UE信息: UE {UeId1} 和 UE {UeId2}", ueId1, ueId2);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, "合并UE信息失败: UE {UeId1} 和 UE {UeId2}", ueId1, ueId2);
+ throw new UeInfoException(Math.Min(ueId1, ueId2), $"合并UE信息失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 创建新的UE信息
+ ///
+ /// UE ID
+ /// 创建的UE信息
+ private UEInfo CreateUeInfo(int ueId)
+ {
+ var ueInfo = new UEInfo
+ {
+ UeId = ueId,
+ Caps = new ProtocolCaps { UeId = ueId }
+ };
+
+ UeList[ueId] = ueInfo;
+ _logger?.LogDebug("创建新的UE信息: UE {UeId}", ueId);
+ return ueInfo;
+ }
+
+ ///
+ /// 获取UE信息
+ ///
+ /// UE ID
+ /// UE信息,如果不存在则返回null
+ public UEInfo? GetUeInfo(int ueId)
+ {
+ if (ueId <= 0)
+ {
+ _logger?.LogWarning("尝试获取无效UE ID的信息: {UeId}", ueId);
+ return null;
+ }
+
+ lock (_lockObject)
+ {
+ return UeList.TryGetValue(ueId, out var ueInfo) ? ueInfo : null;
+ }
+ }
+
+ ///
+ /// 获取UE能力信息,如果不存在则创建
+ /// 同时根据ImsiToUeId映射表更新IMSI信息
+ ///
+ /// UE ID
+ /// UE能力信息
+ public ProtocolCaps GetUeCaps(int ueId)
+ {
+ if (ueId <= 0)
+ {
+ throw new UeInfoException(ueId, "UE ID必须大于0");
+ }
+
+ lock (_lockObject)
+ {
+ if (!UeList.TryGetValue(ueId, out var ueInfo) || ueInfo == null)
+ {
+ ueInfo = CreateUeInfo(ueId);
+ }
+
+ if (ueInfo.Caps == null)
+ {
+ ueInfo.Caps = new ProtocolCaps { UeId = ueId };
+ }
+
+ // 根据ImsiToUeId映射表更新IMSI信息
+ UpdateImsiFromMapping(ueId, ueInfo);
+
+ return ueInfo.Caps;
+ }
+ }
+
+ ///
+ /// 根据ImsiToUeId映射表更新UE的IMSI信息
+ /// 性能优化:使用LINQ提高查找效率
+ ///
+ /// UE ID
+ /// UE信息对象
+ private void UpdateImsiFromMapping(int ueId, UEInfo ueInfo)
+ {
+ var imsiMapping = ImsiToUeId.FirstOrDefault(kvp => kvp.Value.Contains(ueId));
+ if (!string.IsNullOrEmpty(imsiMapping.Key))
+ {
+ ueInfo.Imsi = imsiMapping.Key;
+ _logger?.LogDebug("更新UE {UeId} 的IMSI信息: {Imsi}", ueId, imsiMapping.Key);
+ }
+ }
+
+ ///
+ /// 从现有UE ID同步IMSI信息到新的UE ID
+ ///
+ /// 现有UE ID
+ /// 新的UE ID
+ private void SyncImsiFromExistingUe(int existingUeId, int newUeId)
+ {
+ var imsiMapping = ImsiToUeId.FirstOrDefault(kvp => kvp.Value.Contains(existingUeId));
+ if (!string.IsNullOrEmpty(imsiMapping.Key))
+ {
+ SetImsi(newUeId, imsiMapping.Key);
+ _logger?.LogDebug("同步IMSI信息: 从UE {ExistingUeId} 到 UE {NewUeId}: {Imsi}",
+ existingUeId, newUeId, imsiMapping.Key);
+ }
+ }
+
+ ///
+ /// 从现有UE ID同步PLMN信息到新的UE ID
+ ///
+ /// 现有UE ID
+ /// 新的UE ID
+ private void SyncPlmnFromExistingUe(int existingUeId, int newUeId)
+ {
+ var plmnMapping = PlmnToUeId.FirstOrDefault(kvp => kvp.Value.Contains(existingUeId));
+ if (!string.IsNullOrEmpty(plmnMapping.Key))
+ {
+ SetPlmn(newUeId, plmnMapping.Key);
+ _logger?.LogDebug("同步PLMN信息: 从UE {ExistingUeId} 到 UE {NewUeId}: {Plmn}",
+ existingUeId, newUeId, plmnMapping.Key);
+ }
+ }
+
+ ///
+ /// 获取UeList中UEInfo.UeId与Caps.UeId组合的字典
+ ///
+ /// 包含UE ID和Caps UeId组合的字典,键为UEInfo.UeId,值为Caps.UeId
+ public Dictionary GetUeIdToCapsUeIdMapping()
+ {
+ lock (_lockObject)
+ {
+ var mapping = new Dictionary();
+
+ foreach (var kvp in UeList)
+ {
+ var ueId = kvp.Key;
+ var ueInfo = kvp.Value;
+
+ if (ueInfo?.Caps != null)
+ {
+ mapping[ueId] = ueInfo.Caps.UeId;
+ }
+ }
+
+ return mapping;
+ }
+ }
+
+ ///
+ /// 批量获取UE信息
+ /// 性能优化:批量处理减少锁开销
+ ///
+ /// UE ID列表
+ /// UE信息字典
+ public Dictionary GetUeInfoBatch(IEnumerable ueIds)
+ {
+ if (ueIds == null)
+ {
+ throw new ArgumentNullException(nameof(ueIds));
+ }
+
+ var result = new Dictionary();
+ lock (_lockObject)
+ {
+ foreach (var ueId in ueIds)
+ {
+ if (UeList.TryGetValue(ueId, out var ueInfo))
+ {
+ result[ueId] = ueInfo;
+ }
+ }
+ }
+
+ _logger?.LogDebug("批量获取UE信息,共获取 {Count} 个UE的信息", result.Count);
+ return result;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.ProtocolClient/CoreAgent.ProtocolClient.csproj b/CoreAgent.ProtocolClient/CoreAgent.ProtocolClient.csproj
index 398bd41..d949a47 100644
--- a/CoreAgent.ProtocolClient/CoreAgent.ProtocolClient.csproj
+++ b/CoreAgent.ProtocolClient/CoreAgent.ProtocolClient.csproj
@@ -12,8 +12,4 @@
-
-
-
-
diff --git a/CoreAgent.ProtocolClient/Docs/MessageIdManager.md b/CoreAgent.ProtocolClient/Docs/MessageIdManager.md
new file mode 100644
index 0000000..20ba274
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Docs/MessageIdManager.md
@@ -0,0 +1,509 @@
+# MessageIdManager.cs (自动转换为Markdown)
+
+```csharp
+// 以下内容为原始C#代码,含详细注释
+// 文件原路径:Managers/MessageIdManager.cs
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CoreAgent.ProtocolClient.HandlerEventArgs;
+using CoreAgent.ProtocolClient.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json.Linq;
+
+namespace CoreAgent.ProtocolClient.Managers
+{
+ ///
+ /// 消息ID管理器 - 改进版
+ ///
+ /// 修复的问题:
+ /// 1. 使用long类型防止ID溢出
+ /// 2. 完善消息处理器清理机制
+ /// 3. 改进LogGet ID管理逻辑
+ /// 4. 增强参数验证和异常处理
+ /// 5. 优化性能,减少字符串操作
+ /// 6. 添加线程安全保护
+ /// 7. 改进日志记录格式
+ ///
+ /// 设计原则:
+ /// - 单一职责:专门负责消息ID管理
+ /// - 开闭原则:支持扩展不同类型的消息ID管理
+ /// - 线程安全:所有操作都是线程安全的
+ /// - 性能优化:减少不必要的内存分配
+ /// - 错误处理:完善的异常处理和参数验证
+ ///
+ public class MessageIdManager : IDisposable
+ {
+ #region 私有字段
+
+ private readonly ILogger _logger;
+ private readonly string _clientName;
+ private readonly ConcurrentDictionary _messageHandlers;
+ private readonly ConcurrentDictionary _messageHandlersByName;
+
+ // 使用long类型防止溢出
+ private long _generalMessageId;
+ private long _logGetMessageId;
+
+ // 状态管理
+ private bool _disposed;
+
+ // 性能优化:缓存字符串构建器
+ private readonly StringBuilder _logBuilder = new StringBuilder(256);
+
+ #endregion
+
+ #region 事件
+
+ ///
+ /// 日志获取ID变化事件
+ ///
+ public event EventHandler? LogGetIdChanged;
+
+ ///
+ /// 消息处理器清理事件
+ ///
+ public event EventHandler? HandlerCleanup;
+
+ #endregion
+
+ #region 属性
+
+ ///
+ /// 当前通用消息ID
+ ///
+ public long CurrentGeneralMessageId => Interlocked.Read(ref _generalMessageId);
+
+ ///
+ /// 当前日志获取消息ID
+ ///
+ public long CurrentLogGetMessageId => Interlocked.Read(ref _logGetMessageId);
+
+ ///
+ /// 是否已释放
+ ///
+ public bool IsDisposed => _disposed;
+
+ ///
+ /// 消息处理器数量
+ ///
+ public int MessageHandlerCount => _messageHandlers.Count;
+
+ ///
+ /// 按名称的消息处理器数量
+ ///
+ public int NamedMessageHandlerCount => _messageHandlersByName.Count;
+
+ ///
+ /// 总处理器数量
+ ///
+ public int TotalHandlerCount => MessageHandlerCount + NamedMessageHandlerCount;
+
+ #endregion
+
+ #region 构造函数
+
+ ///
+ /// 构造函数
+ ///
+ /// 客户端名称
+ /// 日志记录器
+ public MessageIdManager(string clientName, ILogger logger)
+ {
+ _clientName = clientName ?? throw new ArgumentNullException(nameof(clientName));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+
+ _messageHandlers = new ConcurrentDictionary();
+ _messageHandlersByName = new ConcurrentDictionary();
+
+ _generalMessageId = 0;
+ _logGetMessageId = -1; // 初始化为-1,表示未开始
+
+ _logger.LogInformation("[{ClientName}] 创建消息ID管理器,初始LogGet ID: {LogGetId}", _clientName, _logGetMessageId);
+ }
+
+ #endregion
+
+ #region 公共方法
+
+ ///
+ /// 生成通用消息ID
+ ///
+ /// 消息对象
+ /// 回调函数
+ /// 是否为错误处理器
+ /// 消息ID
+ public long GenerateGeneralMessageId(JObject message, Action? callback = null, bool errorHandler = false)
+ {
+ ThrowIfDisposed();
+ ValidateMessage(message);
+
+ var id = GetNextMessageId();
+ message["message_id"] = id;
+
+ // 记录log_get消息的发送
+ var messageType = message["message"]?.ToString();
+ if (messageType == "log_get")
+ {
+ LogLogGetMessage(id, message);
+ }
+
+ // 注册回调处理器
+ if (callback != null)
+ {
+ _messageHandlers[id] = new MessageHandler
+ {
+ Callback = callback,
+ ErrorHandler = errorHandler,
+ CreatedAt = DateTime.UtcNow
+ };
+ }
+
+ _logger.LogDebug("[{ClientName}] 生成通用消息ID: {MessageId}", _clientName, id);
+ return id;
+ }
+
+ ///
+ /// 生成日志获取消息ID - 改进版
+ ///
+ /// 消息对象
+ /// 回调函数
+ /// 消息ID
+ public long GenerateLogGetMessageId(JObject message, Action callback)
+ {
+ ThrowIfDisposed();
+ ValidateMessage(message);
+
+ if (callback == null)
+ throw new ArgumentNullException(nameof(callback));
+
+ // 生成新的消息ID
+ var newLogGetId = GetNextMessageId();
+ message["message_id"] = newLogGetId;
+
+ // 注册回调处理器
+ _messageHandlers[newLogGetId] = new MessageHandler
+ {
+ Callback = callback,
+ ErrorHandler = false,
+ CreatedAt = DateTime.UtcNow,
+ IsLogGetHandler = true
+ };
+
+ // 设置新的LogGet ID
+ var oldLogGetId = Interlocked.Exchange(ref _logGetMessageId, newLogGetId);
+
+ // 触发事件
+ LogGetIdChanged?.Invoke(this, new LogGetIdChangedEventArgs(oldLogGetId, newLogGetId));
+
+ _logger.LogDebug("[{ClientName}] LogGet ID变化: {OldId} -> {NewId}", _clientName, oldLogGetId, newLogGetId);
+ return newLogGetId;
+ }
+
+ ///
+ /// 处理消息响应 - 改进版
+ ///
+ /// 响应消息
+ /// 错误处理回调
+ /// 是否找到并处理了消息处理器
+ public bool HandleMessageResponse(JObject response, Action? errorHandler = null)
+ {
+ ThrowIfDisposed();
+
+ if (response == null)
+ return false;
+
+ // 检查消息处理器
+ var id = response["message_id"]?.Value();
+ if (id.HasValue && _messageHandlers.TryGetValue(id.Value, out var handler))
+ {
+ return HandleMessageHandler(id.Value, handler, response, errorHandler);
+ }
+
+ // 检查按名称的消息处理器
+ var name = response["message"]?.ToString();
+ if (!string.IsNullOrEmpty(name) && _messageHandlersByName.TryGetValue(name, out var nameHandler))
+ {
+ return HandleNamedMessageHandler(name, nameHandler, response);
+ }
+
+ return false;
+ }
+
+ ///
+ /// 设置消息处理器
+ ///
+ /// 消息名称数组
+ /// 处理器
+ public void SetMessageHandler(string[] names, MessageHandler handler)
+ {
+ ThrowIfDisposed();
+
+ if (names == null || names.Length == 0)
+ throw new ArgumentException("消息名称不能为空", nameof(names));
+
+ if (handler == null)
+ throw new ArgumentNullException(nameof(handler));
+
+ foreach (var name in names)
+ {
+ if (!string.IsNullOrEmpty(name))
+ {
+ _messageHandlersByName[name] = handler;
+ }
+ }
+
+ _logger.LogDebug("[{ClientName}] 设置消息处理器: {Names}", _clientName, string.Join(", ", names));
+ }
+
+ ///
+ /// 取消消息处理器
+ ///
+ /// 消息名称数组
+ public void UnsetMessageHandler(string[] names)
+ {
+ ThrowIfDisposed();
+
+ if (names == null || names.Length == 0)
+ return;
+
+ foreach (var name in names)
+ {
+ if (!string.IsNullOrEmpty(name))
+ {
+ _messageHandlersByName.TryRemove(name, out _);
+ }
+ }
+
+ _logger.LogDebug("[{ClientName}] 取消消息处理器: {Names}", _clientName, string.Join(", ", names));
+ }
+
+ ///
+ /// 检查是否为当前日志获取消息
+ ///
+ /// 消息ID
+ /// 是否为当前日志获取消息
+ public bool IsCurrentLogGetMessage(long messageId)
+ {
+ var currentLogGetId = Interlocked.Read(ref _logGetMessageId);
+ return messageId == currentLogGetId;
+ }
+
+ ///
+ /// 重置日志获取ID
+ ///
+ public void ResetLogGetId()
+ {
+ var oldLogGetId = Interlocked.Exchange(ref _logGetMessageId, -1);
+ LogGetIdChanged?.Invoke(this, new LogGetIdChangedEventArgs(oldLogGetId, -1));
+ _logger.LogDebug("[{ClientName}] 重置LogGet ID: {OldId} -> -1", _clientName, oldLogGetId);
+ }
+
+ ///
+ /// 清理过期的消息处理器 - 改进版
+ ///
+ /// 最大年龄(毫秒)
+ /// 清理的处理器数量
+ public int CleanupExpiredHandlers(int maxAge = 30000) // 默认30秒
+ {
+ ThrowIfDisposed();
+
+ var now = DateTime.UtcNow;
+ var expiredKeys = new List();
+
+ foreach (var kvp in _messageHandlers)
+ {
+ if (kvp.Value.CreatedAt.AddMilliseconds(maxAge) < now)
+ {
+ expiredKeys.Add(kvp.Key);
+ }
+ }
+
+ var cleanedCount = 0;
+ foreach (var key in expiredKeys)
+ {
+ if (_messageHandlers.TryRemove(key, out _))
+ {
+ cleanedCount++;
+ }
+ }
+
+ if (cleanedCount > 0)
+ {
+ _logger.LogDebug("[{ClientName}] 清理了 {CleanedCount} 个过期的消息处理器", _clientName, cleanedCount);
+
+ // 触发清理事件
+ HandlerCleanup?.Invoke(this, new HandlerCleanupEventArgs(
+ _messageHandlers.Count,
+ _messageHandlersByName.Count,
+ cleanedCount));
+ }
+
+ return cleanedCount;
+ }
+
+ #endregion
+
+ #region 私有方法
+
+ ///
+ /// 获取下一个消息ID
+ ///
+ /// 消息ID
+ private long GetNextMessageId()
+ {
+ var id = Interlocked.Increment(ref _generalMessageId);
+
+ // 检查溢出
+ if (id <= 0)
+ {
+ _logger.LogWarning("[{ClientName}] 消息ID溢出,重置为1", _clientName);
+ Interlocked.Exchange(ref _generalMessageId, 1);
+ return 1;
+ }
+
+ return id;
+ }
+
+ ///
+ /// 验证消息对象
+ ///
+ /// 消息对象
+ private void ValidateMessage(JObject message)
+ {
+ if (message == null)
+ throw new ArgumentNullException(nameof(message));
+ }
+
+ ///
+ /// 处理消息处理器
+ ///
+ /// 消息ID
+ /// 处理器
+ /// 响应消息
+ /// 错误处理回调
+ /// 是否处理成功
+ private bool HandleMessageHandler(long id, MessageHandler handler, JObject response, Action? errorHandler)
+ {
+ // 如果不是通知消息,则移除处理器
+ if (response["notification"]?.Value() != true)
+ {
+ _messageHandlers.TryRemove(id, out _);
+ }
+
+ // 处理错误
+ if (response["error"] != null)
+ {
+ if (!handler.ErrorHandler)
+ {
+ errorHandler?.Invoke(response["error"]?.ToString() ?? "未知错误");
+ }
+ else
+ {
+ handler.Callback?.Invoke(response);
+ }
+ return true;
+ }
+
+ // 正常处理
+ handler.Callback?.Invoke(response);
+ return true;
+ }
+
+ ///
+ /// 处理按名称的消息处理器
+ ///
+ /// 消息名称
+ /// 处理器
+ /// 响应消息
+ /// 是否处理成功
+ private bool HandleNamedMessageHandler(string name, MessageHandler handler, JObject response)
+ {
+ handler.Callback?.Invoke(response);
+ return true;
+ }
+
+ ///
+ /// 记录LogGet消息
+ ///
+ /// 消息ID
+ /// 消息对象
+ private void LogLogGetMessage(long id, JObject message)
+ {
+ _logBuilder.Clear();
+ _logBuilder.AppendFormat("[{0}] 发送log_get消息: message_id={1}", _clientName, id);
+
+ if (message["timeout"] != null)
+ _logBuilder.AppendFormat(", timeout={0}", message["timeout"]);
+
+ if (message["headers"] != null)
+ _logBuilder.AppendFormat(", headers={0}", message["headers"]);
+
+ _logBuilder.AppendFormat(", ThreadId={0}", Thread.CurrentThread.ManagedThreadId);
+
+ _logger.LogDebug(_logBuilder.ToString());
+ }
+
+ ///
+ /// 检查是否已释放
+ ///
+ private void ThrowIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(nameof(MessageIdManager));
+ }
+ }
+
+ #endregion
+
+ #region IDisposable
+
+ ///
+ /// 释放资源
+ ///
+ public void Dispose()
+ {
+ if (_disposed) return;
+
+ _disposed = true;
+
+ // 清理所有消息处理器
+ _messageHandlers.Clear();
+ _messageHandlersByName.Clear();
+
+ _logger.LogInformation("[{ClientName}] 释放消息ID管理器", _clientName);
+ }
+
+ #endregion
+ }
+}
+```
+
+## 文档说明
+
+### 类概述
+`MessageIdManager` 是一个专门负责消息ID管理的类,用于替代原始实现中的 `_messageId` 和 `_logGetId` 字段,提供更统一和强大的消息ID管理功能。
+
+### 主要功能
+1. **消息ID生成**:统一管理通用消息ID和日志获取消息ID
+2. **消息处理器管理**:管理消息回调处理器,支持按ID和按名称两种方式
+3. **线程安全**:所有操作都是线程安全的
+4. **自动清理**:支持自动清理过期的消息处理器
+5. **事件通知**:提供LogGet ID变化和处理器清理的事件通知
+
+### 设计改进
+- 使用long类型防止ID溢出
+- 完善的异常处理和参数验证
+- 性能优化,减少字符串操作
+- 标准的Dispose模式实现
+- 详细的日志记录
+
+### 使用场景
+- 在WebSocket消息管理器中统一管理消息ID
+- 处理消息响应和回调
+- 管理日志获取流程
+- 提供消息处理器的生命周期管理
\ No newline at end of file
diff --git a/CoreAgent.ProtocolClient/Enums/TmsiType.cs b/CoreAgent.ProtocolClient/Enums/TmsiType.cs
new file mode 100644
index 0000000..4cc52eb
--- /dev/null
+++ b/CoreAgent.ProtocolClient/Enums/TmsiType.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CoreAgent.ProtocolClient.Enums
+{
+ ///
+ /// TMSI类型
+ ///
+ public enum TmsiType
+ {
+ ///
+ /// 接受类型
+ ///
+ Accept,
+
+ ///
+ /// 请求类型
+ ///
+ Request,
+
+ ///
+ /// 服务请求类型
+ ///
+ ServiceRequest
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.ProtocolClient/Managers/MessageIdManager.cs b/CoreAgent.ProtocolClient/Managers/MessageIdManager.cs
index c782eb3..8fd30df 100644
--- a/CoreAgent.ProtocolClient/Managers/MessageIdManager.cs
+++ b/CoreAgent.ProtocolClient/Managers/MessageIdManager.cs
@@ -12,29 +12,13 @@ using Newtonsoft.Json.Linq;
namespace CoreAgent.ProtocolClient.Managers
{
///
- /// 消息ID管理器 - 改进版
- ///
- /// 修复的问题:
- /// 1. 使用long类型防止ID溢出
- /// 2. 完善消息处理器清理机制
- /// 3. 改进LogGet ID管理逻辑
- /// 4. 增强参数验证和异常处理
- /// 5. 优化性能,减少字符串操作
- /// 6. 添加线程安全保护
- /// 7. 改进日志记录格式
- ///
- /// 设计原则:
- /// - 单一职责:专门负责消息ID管理
- /// - 开闭原则:支持扩展不同类型的消息ID管理
- /// - 线程安全:所有操作都是线程安全的
- /// - 性能优化:减少不必要的内存分配
- /// - 错误处理:完善的异常处理和参数验证
+ /// 消息ID管理器
///
public class MessageIdManager : IDisposable
{
#region 私有字段
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
private readonly string _clientName;
private readonly ConcurrentDictionary _messageHandlers;
private readonly ConcurrentDictionary _messageHandlersByName;
@@ -104,9 +88,7 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 构造函数
///
- /// 客户端名称
- /// 日志记录器
- public MessageIdManager(string clientName, ILogger logger)
+ public MessageIdManager(string clientName, ILogger logger)
{
_clientName = clientName ?? throw new ArgumentNullException(nameof(clientName));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -127,10 +109,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 生成通用消息ID
///
- /// 消息对象
- /// 回调函数
- /// 是否为错误处理器
- /// 消息ID
public long GenerateGeneralMessageId(JObject message, Action? callback = null, bool errorHandler = false)
{
ThrowIfDisposed();
@@ -162,11 +140,8 @@ namespace CoreAgent.ProtocolClient.Managers
}
///
- /// 生成日志获取消息ID - 改进版
+ /// 生成日志获取消息ID
///
- /// 消息对象
- /// 回调函数
- /// 消息ID
public long GenerateLogGetMessageId(JObject message, Action callback)
{
ThrowIfDisposed();
@@ -199,11 +174,8 @@ namespace CoreAgent.ProtocolClient.Managers
}
///
- /// 处理消息响应 - 改进版
+ /// 处理消息响应
///
- /// 响应消息
- /// 错误处理回调
- /// 是否找到并处理了消息处理器
public bool HandleMessageResponse(JObject response, Action? errorHandler = null)
{
ThrowIfDisposed();
@@ -231,8 +203,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 设置消息处理器
///
- /// 消息名称数组
- /// 处理器
public void SetMessageHandler(string[] names, MessageHandler handler)
{
ThrowIfDisposed();
@@ -257,7 +227,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 取消消息处理器
///
- /// 消息名称数组
public void UnsetMessageHandler(string[] names)
{
ThrowIfDisposed();
@@ -279,8 +248,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 检查是否为当前日志获取消息
///
- /// 消息ID
- /// 是否为当前日志获取消息
public bool IsCurrentLogGetMessage(long messageId)
{
var currentLogGetId = Interlocked.Read(ref _logGetMessageId);
@@ -298,10 +265,8 @@ namespace CoreAgent.ProtocolClient.Managers
}
///
- /// 清理过期的消息处理器 - 改进版
+ /// 清理过期的消息处理器
///
- /// 最大年龄(毫秒)
- /// 清理的处理器数量
public int CleanupExpiredHandlers(int maxAge = 30000) // 默认30秒
{
ThrowIfDisposed();
@@ -340,7 +305,6 @@ namespace CoreAgent.ProtocolClient.Managers
return cleanedCount;
}
-
#endregion
#region 私有方法
@@ -348,7 +312,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 获取下一个消息ID
///
- /// 消息ID
private long GetNextMessageId()
{
var id = Interlocked.Increment(ref _generalMessageId);
@@ -367,7 +330,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 验证消息对象
///
- /// 消息对象
private void ValidateMessage(JObject message)
{
if (message == null)
@@ -377,11 +339,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 处理消息处理器
///
- /// 消息ID
- /// 处理器
- /// 响应消息
- /// 错误处理回调
- /// 是否处理成功
private bool HandleMessageHandler(long id, MessageHandler handler, JObject response, Action? errorHandler)
{
// 如果不是通知消息,则移除处理器
@@ -412,10 +369,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 处理按名称的消息处理器
///
- /// 消息名称
- /// 处理器
- /// 响应消息
- /// 是否处理成功
private bool HandleNamedMessageHandler(string name, MessageHandler handler, JObject response)
{
handler.Callback?.Invoke(response);
@@ -425,8 +378,6 @@ namespace CoreAgent.ProtocolClient.Managers
///
/// 记录LogGet消息
///
- /// 消息ID
- /// 消息对象
private void LogLogGetMessage(long id, JObject message)
{
_logBuilder.Clear();
diff --git a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Constructor.cs b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Constructor.cs
index 9285813..3522936 100644
--- a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Constructor.cs
+++ b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Constructor.cs
@@ -15,40 +15,20 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
{
#region 构造函数
- ///
- /// 构造函数 - 对应LTEClientWebSocket构造函数中的WebSocket相关初始化
- ///
- /// 初始化说明:
- /// 1. 创建MessageIdManager替代原始的_messageId和_logGetId字段
- /// 2. 创建消息队列_messageFifo,保持与原始实现一致
- /// 3. 不初始化WebSocket实例,在Connect方法中创建
- /// 4. 移除_sentMessages和_receivedMessages的初始化
- ///
- /// 对应关系:
- /// - 参数clientName:对应LTEClientWebSocket构造函数中的config.Name
- /// - 参数logger:对应LTEClientWebSocket构造函数中的logger参数
- /// - _messageIdManager:替代原始的_messageId和_logGetId字段
- /// - _messageFifo:对应原始的_messageFifo初始化
- /// - _disposed:对应原始的_disposed初始化
- /// - 日志记录:对应原始的构造函数日志记录
- ///
- /// 重构改进:
- /// - 参数验证:增加了对clientName和logger的null检查
- /// - 职责分离:专注于WebSocket相关初始化
- /// - 功能增强:通过MessageIdManager提供更好的消息ID管理
- /// - 移除冗余:移除了消息缓存相关的初始化
- ///
- /// 客户端名称,对应LTEClientWebSocket._config.Name
- /// 日志记录器,对应LTEClientWebSocket._logger
- public WebSocketMessageManager(string clientName, ILogger logger)
+ public WebSocketMessageManager(string clientName, ILoggerFactory loggerFactory)
{
+ // 参数验证
_clientName = clientName ?? throw new ArgumentNullException(nameof(clientName));
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ var factory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
- // 创建MessageIdManager,替代原始的_messageId和_logGetId字段
- _messageIdManager = new MessageIdManager(clientName, logger);
+ // 创建自己的Logger
+ _logger = factory.CreateLogger();
- // 创建消息队列,使用BlockingCollection优化线程安全性和性能
+ // 初始化消息ID管理器 - 使用ILoggerFactory创建正确的logger类型
+ var messageIdLogger = factory.CreateLogger();
+ _messageIdManager = new MessageIdManager(clientName, messageIdLogger);
+
+ // 创建消息队列
_messageFifo = new BlockingCollection();
_logger.LogInformation($"[{_clientName}] 创建WebSocket消息管理器");
diff --git a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Dispose.cs b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Dispose.cs
index e99f0d3..cb92155 100644
--- a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Dispose.cs
+++ b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/Dispose.cs
@@ -16,27 +16,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
#region IDisposable实现
///
- /// 释放资源 - 对应LTEClientWebSocket.Dispose()方法
- ///
- /// 功能说明:
- /// 1. 释放WebSocket连接和相关资源
- /// 2. 清理消息队列和定时器
- /// 3. 设置释放标志,防止重复释放
- /// 4. 调用MessageIdManager的Dispose方法
- ///
- /// 对应关系:
- /// - 资源释放:对应原始实现中的Dispose()方法
- /// - 连接关闭:对应原始实现中的WebSocket关闭逻辑
- /// - 定时器清理:对应原始实现中的定时器释放逻辑
- /// - 队列清理:对应原始实现中的队列清理逻辑
- /// - 释放标志:对应原始实现中的_disposed设置
- /// - 日志记录:对应原始实现中的释放日志记录
- ///
- /// 重构改进:
- /// - 更清晰的资源释放顺序
- /// - 更完善的异常处理
- /// - 更详细的日志记录
- /// - 保持了完全一致的释放逻辑
+ /// 释放资源
///
public void Dispose()
{
@@ -45,25 +25,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 释放资源的受保护方法 - 实现标准的Dispose模式
- ///
- /// 功能说明:
- /// 1. 实现标准的Dispose模式,支持手动释放和垃圾回收
- /// 2. 确保资源只被释放一次
- /// 3. 按照正确的顺序释放资源
- ///
- /// 对应关系:
- /// - 释放模式:对应.NET标准的Dispose模式
- /// - 资源清理:对应原始实现中的资源清理逻辑
- /// - 异常处理:对应原始实现中的异常处理
- ///
- /// 重构改进:
- /// - 标准的Dispose模式实现
- /// - 更安全的资源管理
- /// - 更好的异常处理
- /// - 保持了完全一致的清理逻辑
+ /// 释放资源的受保护方法
///
- /// 是否为手动释放
protected virtual void Dispose(bool disposing)
{
if (_disposed)
@@ -75,23 +38,23 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
{
_logger.LogInformation($"[{_clientName}] 释放WebSocket消息管理器资源");
- // 停止消息发送定时器 - 对应原始实现中的定时器释放
+ // 停止消息发送定时器
StopMessageDeferTimer();
- // 清空消息队列 - 对应原始实现中的队列清理
+ // 清空消息队列
ClearMessageQueue();
- // 释放BlockingCollection资源 - 优化:确保BlockingCollection正确释放
+ // 释放BlockingCollection资源
_messageFifo?.Dispose();
- // 关闭WebSocket连接 - 对应原始实现中的WebSocket关闭
+ // 关闭WebSocket连接
if (_webSocket != null)
{
_webSocket.Close();
_webSocket = null;
}
- // 释放MessageIdManager - 对应原始实现中的相关资源释放
+ // 释放MessageIdManager
_messageIdManager?.Dispose();
}
catch (Exception ex)
diff --git a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PrivateMethods.cs b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PrivateMethods.cs
index 370199a..e2ca335 100644
--- a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PrivateMethods.cs
+++ b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PrivateMethods.cs
@@ -16,22 +16,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
#region 私有方法
///
- /// 检查对象是否已释放,如果已释放则抛出异常
- ///
- /// 功能说明:
- /// 1. 检查_disposed字段,如果为true则抛出ObjectDisposedException
- /// 2. 在所有公共方法开始时调用,确保对象状态正确
- /// 3. 提供统一的释放状态检查逻辑
- ///
- /// 对应关系:
- /// - 检查逻辑:对应原始实现中的_disposed检查
- /// - 异常类型:ObjectDisposedException,与.NET标准一致
- /// - 使用场景:在所有公共方法开始时调用
- ///
- /// 重构改进:
- /// - 统一的释放状态检查
- /// - 更清晰的异常信息
- /// - 更好的代码复用
+ /// 检查对象是否已释放
///
private void ThrowIfDisposed()
{
@@ -40,25 +25,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// WebSocket连接打开事件处理器 - 对应LTEClientWebSocket.OnSocketOpened
- ///
- /// 功能说明:
- /// 1. 处理WebSocket连接成功建立事件
- /// 2. 记录连接成功日志
- /// 3. 触发ConnectionOpened事件
- ///
- /// 对应关系:
- /// - 事件处理:对应原始实现中的OnSocketOpened方法
- /// - 日志记录:对应原始实现中的连接成功日志
- /// - 事件触发:对应原始实现中的ConnectionOpened事件触发
- ///
- /// 重构改进:
- /// - 更清晰的日志记录
- /// - 更好的异常处理
- /// - 保持了完全一致的事件处理逻辑
+ /// WebSocket连接打开事件处理器
///
- /// 事件发送者
- /// 事件参数
private void OnSocketOpened(object? sender, EventArgs e)
{
try
@@ -73,25 +41,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// WebSocket连接关闭事件处理器 - 对应LTEClientWebSocket.OnSocketClosed
- ///
- /// 功能说明:
- /// 1. 处理WebSocket连接关闭事件
- /// 2. 记录连接关闭日志
- /// 3. 触发ConnectionClosed事件
- ///
- /// 对应关系:
- /// - 事件处理:对应原始实现中的OnSocketClosed方法
- /// - 日志记录:对应原始实现中的连接关闭日志
- /// - 事件触发:对应原始实现中的ConnectionClosed事件触发
- ///
- /// 重构改进:
- /// - 更清晰的日志记录
- /// - 更好的异常处理
- /// - 保持了完全一致的事件处理逻辑
+ /// WebSocket连接关闭事件处理器
///
- /// 事件发送者
- /// 事件参数
private void OnSocketClosed(object? sender, EventArgs e)
{
try
@@ -106,27 +57,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// WebSocket消息接收事件处理器 - 对应LTEClientWebSocket.OnSocketMessage
- ///
- /// 功能说明:
- /// 1. 处理WebSocket消息接收事件
- /// 2. 解析接收到的消息
- /// 3. 触发MessageReceived事件
- /// 4. 调用HandleReceivedMessage处理消息
- ///
- /// 对应关系:
- /// - 事件处理:对应原始实现中的OnSocketMessage方法
- /// - 消息解析:对应原始实现中的消息解析逻辑
- /// - 事件触发:对应原始实现中的MessageReceived事件触发
- /// - 消息处理:对应原始实现中的消息处理逻辑
- ///
- /// 重构改进:
- /// - 更清晰的错误处理
- /// - 更详细的日志记录
- /// - 保持了完全一致的事件处理逻辑
+ /// WebSocket消息接收事件处理器
///
- /// 事件发送者
- /// 消息接收事件参数
private void OnSocketMessageReceived(object? sender, MessageReceivedEventArgs e)
{
try
@@ -134,7 +66,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
var messageText = e.Message;
_logger.LogDebug($"[{_clientName}] 接收到消息: {messageText}");
- // 解析消息 - 对应原始实现中的消息解析逻辑
+ // 解析消息
JObject? message = null;
try
{
@@ -147,10 +79,10 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
return;
}
- // 触发MessageReceived事件 - 对应原始实现中的事件触发
+ // 触发MessageReceived事件
MessageReceived?.Invoke(this, message);
- // 处理消息 - 对应原始实现中的消息处理逻辑
+ // 处理消息
HandleReceivedMessage(message, error => ConnectionError?.Invoke(this, error));
}
catch (Exception ex)
@@ -161,25 +93,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// WebSocket错误事件处理器 - 对应LTEClientWebSocket.OnSocketError
- ///
- /// 功能说明:
- /// 1. 处理WebSocket连接错误事件
- /// 2. 记录错误日志
- /// 3. 触发ConnectionError事件
- ///
- /// 对应关系:
- /// - 事件处理:对应原始实现中的OnSocketError方法
- /// - 错误记录:对应原始实现中的错误日志记录
- /// - 事件触发:对应原始实现中的ConnectionError事件触发
- ///
- /// 重构改进:
- /// - 更详细的错误信息记录
- /// - 更好的异常处理
- /// - 保持了完全一致的事件处理逻辑
+ /// WebSocket错误事件处理器
///
- /// 事件发送者
- /// 错误事件参数
private void OnSocketError(object? sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
try
@@ -195,23 +110,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 启动消息延迟发送定时器 - 对应LTEClientWebSocket.StartMessageDeferTimer
- ///
- /// 功能说明:
- /// 1. 启动消息延迟发送定时器,实现批量发送优化
- /// 2. 当队列中消息少于100条时,延迟1毫秒发送
- /// 3. 当队列中消息达到100条时,立即发送
- ///
- /// 对应关系:
- /// - 定时器创建:对应原始实现中的定时器创建逻辑
- /// - 延迟策略:1毫秒延迟,与原始实现完全一致
- /// - 批处理大小:100条消息,与原始实现完全一致
- /// - 回调函数:对应原始实现中的定时器回调逻辑
- ///
- /// 重构改进:
- /// - 更清晰的定时器管理
- /// - 更好的异常处理
- /// - 保持了完全一致的批处理策略
+ /// 启动消息延迟发送定时器
///
private void StartMessageDeferTimer()
{
@@ -230,22 +129,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 停止消息延迟发送定时器 - 对应LTEClientWebSocket.StopMessageDeferTimer
- ///
- /// 功能说明:
- /// 1. 停止消息延迟发送定时器
- /// 2. 释放定时器资源
- /// 3. 确保线程安全的定时器管理
- ///
- /// 对应关系:
- /// - 定时器停止:对应原始实现中的定时器停止逻辑
- /// - 资源释放:对应原始实现中的定时器释放逻辑
- /// - 线程安全:使用锁确保线程安全
- ///
- /// 重构改进:
- /// - 更清晰的资源管理
- /// - 更好的线程安全保证
- /// - 保持了完全一致的停止逻辑
+ /// 停止消息延迟发送定时器
///
private void StopMessageDeferTimer()
{
@@ -253,35 +137,18 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 消息延迟发送定时器回调 - 对应LTEClientWebSocket.OnMessageDeferTimer
- ///
- /// 功能说明:
- /// 1. 处理消息延迟发送定时器回调
- /// 2. 批量发送队列中的消息
- /// 3. 实现消息发送优化
- ///
- /// 对应关系:
- /// - 定时器回调:对应原始实现中的OnMessageDeferTimer方法
- /// - 批量发送:对应原始实现中的批量发送逻辑
- /// - 批处理大小:100条消息,与原始实现完全一致
- /// - 发送逻辑:对应原始实现中的SendMessageNow调用
- ///
- /// 重构改进:
- /// - 更清晰的批量发送逻辑
- /// - 更好的异常处理
- /// - 保持了完全一致的批处理策略
+ /// 消息延迟发送定时器回调
///
- /// 定时器状态参数
private void OnMessageDeferTimer(object? state)
{
try
{
- // 批量发送消息 - 对应原始实现中的批量发送逻辑
+ // 批量发送消息
var messages = new List();
var count = 0;
- const int batchSize = 100; // 与原始实现完全一致
+ const int batchSize = 100;
- // 从队列中取出消息 - 对应原始实现中的队列处理逻辑
+ // 从队列中取出消息
while (count < batchSize && _messageFifo.TryTake(out var message))
{
messages.Add(message);
@@ -290,11 +157,11 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
if (messages.Count > 0)
{
- // 发送消息 - 对应原始实现中的SendMessageNow调用
+ // 发送消息
SendMessageNow(messages);
}
- // 如果队列中还有消息,继续启动定时器 - 对应原始实现中的定时器重启逻辑
+ // 如果队列中还有消息,继续启动定时器
if (_messageFifo.Count > 0)
{
StartMessageDeferTimer();
@@ -307,26 +174,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 立即发送消息 - 对应LTEClientWebSocket.SendMessageNow
- ///
- /// 功能说明:
- /// 1. 立即发送消息列表到WebSocket
- /// 2. 处理发送异常和错误
- /// 3. 触发MessageSent事件
- ///
- /// 对应关系:
- /// - 消息发送:对应原始实现中的SendMessageNow方法
- /// - 异常处理:对应原始实现中的发送异常处理
- /// - 事件触发:对应原始实现中的事件触发逻辑
- /// - 日志记录:对应原始实现中的发送日志记录
- ///
- /// 重构改进:
- /// - 更清晰的发送逻辑
- /// - 更详细的错误处理
- /// - 新增MessageSent事件触发
- /// - 保持了完全一致的发送逻辑
+ /// 立即发送消息
///
- /// 要发送的消息列表
private void SendMessageNow(List messages)
{
if (messages == null || messages.Count == 0)
@@ -345,7 +194,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
var messageText = JsonConvert.SerializeObject(message);
_webSocket?.Send(messageText);
- // 触发MessageSent事件 - 新增功能,提供更完整的消息生命周期通知
+ // 触发MessageSent事件
MessageSent?.Invoke(this, message);
_logger.LogDebug($"[{_clientName}] 消息已发送: {messageText}");
@@ -359,21 +208,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 清空消息队列 - 对应LTEClientWebSocket中的队列清理逻辑
- ///
- /// 功能说明:
- /// 1. 清空消息队列中的所有消息
- /// 2. 在断开连接时调用,确保资源清理
- ///
- /// 对应关系:
- /// - 队列清理:对应原始实现中的队列清理逻辑
- /// - 调用时机:在Disconnect()方法中调用
- /// - 日志记录:对应原始实现中的清理日志记录
- ///
- /// 重构改进:
- /// - 更清晰的清理逻辑
- /// - 更详细的日志记录
- /// - 保持了完全一致的清理逻辑
+ /// 清空消息队列
///
private void ClearMessageQueue()
{
diff --git a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PublicMethods.cs b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PublicMethods.cs
index 6138f31..b1fcf48 100644
--- a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PublicMethods.cs
+++ b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/PublicMethods.cs
@@ -17,37 +17,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
#region 公共方法
///
- /// 连接到WebSocket服务器 - 对应LTEClientWebSocket.Start()方法
- ///
- /// 功能说明:
- /// 1. 建立WebSocket连接,对应原始Start()方法的核心逻辑
- /// 2. 构建WebSocket URL,支持SSL和非SSL连接
- /// 3. 绑定事件处理器,对应原始的事件绑定逻辑
- /// 4. 提供更严格的参数验证和异常处理
- ///
- /// 与原始实现的差异:
- /// - 方法名从Start()改为Connect(),更明确表达功能
- /// - 移除了状态管理逻辑(SetState),专注连接管理
- /// - 增加了参数验证,提供更好的错误处理
- ///
- /// 详细对应关系:
- /// - 参数url:对应原始实现中的config.Address
- /// - 参数ssl:对应原始实现中的config.Ssl
- /// - URL构建:对应原始实现中的URL构建逻辑
- /// - WebSocket创建:对应原始实现中的_webSocket = new WebSocket(url)
- /// - 事件绑定:对应原始实现中的事件绑定逻辑
- /// - 连接打开:对应原始实现中的_webSocket.Open()
- /// - 异常处理:对应原始实现中的异常处理逻辑
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 更明确的参数验证
- /// - 更详细的异常处理
- /// - 更清晰的错误信息
- /// - 保持了完全一致的连接逻辑
+ /// 连接到WebSocket服务器
///
- /// WebSocket URL,对应LTEClientWebSocket._config.Address
- /// 是否使用SSL,对应LTEClientWebSocket._config.Ssl
public void Connect(string url, bool ssl = false)
{
ThrowIfDisposed();
@@ -59,20 +30,20 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
{
_logger.LogInformation($"[{_clientName}] 尝试连接: {url}");
- // 构建WebSocket URL - 对应原始实现中的URL构建逻辑
+ // 构建WebSocket URL
var fullUrl = (ssl ? "wss://" : "ws://") + url;
- // 创建WebSocket实例 - 对应原始实现中的_webSocket创建
+ // 创建WebSocket实例
_webSocket = new WebSocket(fullUrl);
_webSocket.EnableAutoSendPing = false;
- // 绑定事件处理器 - 对应原始实现中的事件绑定
+ // 绑定事件处理器
_webSocket.Opened += OnSocketOpened!;
_webSocket.Closed += OnSocketClosed!;
- _webSocket.MessageReceived += OnSocketMessageReceived!; // 对应OnSocketMessage0
+ _webSocket.MessageReceived += OnSocketMessageReceived!;
_webSocket.Error += OnSocketError!;
- // 打开连接 - 对应原始实现中的_webSocket.Open()
+ // 打开连接
_webSocket.Open();
}
catch (Exception ex)
@@ -84,31 +55,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 断开WebSocket连接 - 对应LTEClientWebSocket.Stop()方法中的WebSocket相关逻辑
- ///
- /// 功能说明:
- /// 1. 关闭WebSocket连接,对应原始Stop()方法的核心逻辑
- /// 2. 清理消息队列和定时器,对应原始的资源清理逻辑
- /// 3. 提供更完善的异常处理
- ///
- /// 与原始实现的差异:
- /// - 方法名从Stop()改为Disconnect(),更明确表达功能
- /// - 移除了状态管理逻辑(SetState),专注连接管理
- /// - 移除了重连逻辑,专注连接断开
- ///
- /// 详细对应关系:
- /// - 定时器停止:对应原始StopTimers()中的_messageDeferTimer处理
- /// - 队列清理:对应原始实现中的队列清理逻辑
- /// - WebSocket关闭:对应原始实现中的_webSocket.Close()
- /// - 资源清理:对应原始实现中的资源清理逻辑
- /// - 异常处理:对应原始实现中的异常处理
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 更清晰的资源清理顺序
- /// - 更完善的异常处理
- /// - 更详细的日志记录
- /// - 保持了完全一致的清理逻辑
+ /// 断开WebSocket连接
///
public void Disconnect()
{
@@ -118,13 +65,13 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
{
_logger.LogInformation($"[{_clientName}] 断开连接");
- // 停止消息发送定时器 - 对应原始StopTimers()中的_messageDeferTimer处理
+ // 停止消息发送定时器
StopMessageDeferTimer();
- // 清空消息队列 - 对应原始实现中的队列清理
+ // 清空消息队列
ClearMessageQueue();
- // 关闭WebSocket连接 - 对应原始实现中的_webSocket.Close()
+ // 关闭WebSocket连接
if (_webSocket != null)
{
_webSocket.Close();
@@ -138,41 +85,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 发送消息 - 对应LTEClientWebSocket.SendMessage()方法
- ///
- /// 功能说明:
- /// 1. 发送通用消息,对应原始SendMessage()方法的核心逻辑
- /// 2. 使用MessageIdManager生成消息ID,替代原始的Interlocked.Increment(ref _messageId)
- /// 3. 将消息加入队列,对应原始的_messageFifo.Enqueue(message)
- /// 4. 启动延迟发送定时器,对应原始的定时器逻辑
- ///
- /// 与原始实现的差异:
- /// - 消息ID生成通过MessageIdManager,提供更好的管理
- /// - 移除了消息缓存逻辑(_sentMessages),专注传输
- /// - 增加了更严格的参数验证
- /// - 保持了完全一致的队列和定时器逻辑
- ///
- /// 详细对应关系:
- /// - 参数message:对应原始方法中的message参数
- /// - 参数callback:对应原始方法中的callback参数
- /// - 参数errorHandler:对应原始方法中的errorHandler参数
- /// - 连接状态检查:对应原始实现中的连接状态检查
- /// - 消息ID生成:对应原始的Interlocked.Increment(ref _messageId)
- /// - 队列操作:对应原始的_messageFifo.Enqueue(message)
- /// - 定时器启动:对应原始的定时器启动逻辑
- /// - 返回值:对应原始方法的返回值
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 更统一的消息ID管理
- /// - 更严格的参数验证
- /// - 更详细的日志记录
- /// - 保持了完全一致的发送逻辑
+ /// 发送消息
///
- /// 消息对象,对应原始方法中的message参数
- /// 回调函数,对应原始方法中的callback参数
- /// 是否为错误处理器,对应原始方法中的errorHandler参数
- /// 消息ID,对应原始方法的返回值
public long SendMessage(JObject message, Action? callback = null, bool errorHandler = false)
{
ThrowIfDisposed();
@@ -180,20 +94,20 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
if (message == null)
throw new ArgumentNullException(nameof(message));
- // 检查连接状态 - 对应原始实现中的连接状态检查
+ // 检查连接状态
if (!IsConnected)
{
_logger.LogWarning($"[{_clientName}] WebSocket未连接,无法发送消息");
return -1L;
}
- // 使用MessageIdManager生成ID - 替代原始的Interlocked.Increment(ref _messageId)
+ // 使用MessageIdManager生成ID
var messageId = _messageIdManager.GenerateGeneralMessageId(message, callback, errorHandler);
- // 添加到消息队列 - 对应原始实现中的_messageFifo.Enqueue(message)
+ // 添加到消息队列
_messageFifo.Add(message);
- // 启动消息发送定时器 - 对应原始实现中的定时器启动逻辑
+ // 启动消息发送定时器
StartMessageDeferTimer();
_logger.LogDebug($"[{_clientName}] 消息已加入队列: message_id={messageId}");
@@ -201,36 +115,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 发送日志获取消息 - 对应LTEClientWebSocket.LogGet()方法中的消息发送部分
- ///
- /// 功能说明:
- /// 1. 专门用于发送日志获取消息,对应原始LogGet()方法的核心逻辑
- /// 2. 使用MessageIdManager生成LogGet ID,替代原始的_logGetId管理
- /// 3. 委托给SendMessage方法,保持代码一致性
- ///
- /// 与原始实现的差异:
- /// - 专门处理日志获取消息,提供更清晰的接口
- /// - 使用MessageIdManager管理LogGet ID,提供更好的跟踪
- /// - 委托给SendMessage方法,避免代码重复
- /// - 保持了完全一致的发送逻辑
- ///
- /// 详细对应关系:
- /// - 参数message:对应原始LogGet()方法中构建的message
- /// - 参数callback:对应原始LogGet()方法中的LogGetParse回调
- /// - 委托给SendMessage:对应原始实现中的SendMessage调用
- /// - LogGet ID生成:对应原始的_logGetId管理逻辑
- /// - 返回值:对应原始方法的返回值
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 更专门的日志获取消息处理
- /// - 更统一的LogGet ID管理
- /// - 避免代码重复,委托给SendMessage
- /// - 保持了完全一致的发送逻辑
+ /// 发送日志获取消息
///
- /// 消息对象,对应原始LogGet()方法中构建的message
- /// 回调函数,对应原始LogGet()方法中的LogGetParse回调
- /// 消息ID,对应原始方法的返回值
public long SendLogGetMessage(JObject message, Action callback)
{
ThrowIfDisposed();
@@ -241,19 +127,17 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
if (callback == null)
throw new ArgumentNullException(nameof(callback));
- // 检查连接状态 - 对应原始实现中的连接状态检查
+ // 检查连接状态
if (!IsConnected)
{
_logger.LogWarning($"[{_clientName}] WebSocket未连接,无法发送日志获取消息");
return -1L;
}
- // 使用MessageIdManager生成LogGet ID - 替代原始的_logGetId管理
+ // 使用MessageIdManager生成LogGet ID
var messageId = _messageIdManager.GenerateLogGetMessageId(message, callback);
- // 委托给SendMessage方法,避免代码重复 - 对应原始实现中的SendMessage调用
- // 注意:这里不需要再次调用SendMessage,因为GenerateLogGetMessageId已经处理了消息ID和回调注册
- // 只需要将消息加入队列并启动定时器
+ // 将消息加入队列并启动定时器
_messageFifo.Add(message);
StartMessageDeferTimer();
@@ -262,38 +146,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 处理接收到的消息 - 对应LTEClientWebSocket.OnSocketMessage()方法中的消息处理逻辑
- ///
- /// 功能说明:
- /// 1. 处理接收到的WebSocket消息,对应原始OnSocketMessage()方法的核心逻辑
- /// 2. 使用MessageIdManager处理消息响应,替代原始的消息处理器查找逻辑
- /// 3. 触发MessageReceived事件,对应原始的事件触发
- /// 4. 提供完善的错误处理
- ///
- /// 与原始实现的差异:
- /// - 使用MessageIdManager处理消息响应,提供更好的管理
- /// - 移除了消息缓存逻辑(_receivedMessages),专注处理
- /// - 移除了业务逻辑处理(log_get、stats等),专注消息路由
- /// - 保持了完全一致的事件触发逻辑
- ///
- /// 详细对应关系:
- /// - 参数message:对应原始方法中的msg参数
- /// - 参数errorHandler:对应原始方法中的错误处理逻辑
- /// - 消息处理器查找:对应原始的消息处理器查找逻辑
- /// - 事件触发:对应原始的事件触发逻辑
- /// - 错误处理:对应原始的错误处理逻辑
- /// - 返回值:新增返回值提供处理状态反馈
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 更统一的消息响应处理
- /// - 更清晰的错误处理
- /// - 更详细的日志记录
- /// - 保持了完全一致的处理逻辑
+ /// 处理接收到的消息
///
- /// 接收到的消息,对应原始方法中的msg参数
- /// 错误处理回调,对应原始方法中的错误处理逻辑
- /// 是否成功处理,新增返回值提供处理状态反馈
public bool HandleReceivedMessage(JObject message, Action? errorHandler = null)
{
ThrowIfDisposed();
@@ -303,7 +157,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
try
{
- // 使用MessageIdManager处理消息响应 - 替代原始的消息处理器查找逻辑
+ // 使用MessageIdManager处理消息响应
var handled = _messageIdManager.HandleMessageResponse(message, errorHandler);
if (handled)
@@ -312,8 +166,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
return true;
}
- // 处理特定消息类型 - 对应原始实现中的特定消息类型处理
- // 注意:这里不处理log_get和stats等业务逻辑,因为重构版本专注于消息传输
+ // 处理特定消息类型
var name = message["message"]?.ToString();
if (!string.IsNullOrEmpty(name))
{
@@ -331,26 +184,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 设置消息处理器 - 对应LTEClientWebSocket.SetMessageHandler()方法
- ///
- /// 功能说明:
- /// 1. 设置按名称的消息处理器,对应原始SetMessageHandler()方法的核心逻辑
- /// 2. 委托给MessageIdManager处理,提供统一的消息处理器管理
- /// 3. 支持多个消息名称的处理器设置
- ///
- /// 详细对应关系:
- /// - 参数names:对应原始方法中的names参数,消息名称数组
- /// - 参数handler:对应原始方法中的handler参数,消息处理器
- /// - 处理器注册:对应原始的_messageHandlersByName注册逻辑
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 委托给MessageIdManager,提供统一管理
- /// - 保持了完全一致的接口和功能
- /// - 更好的错误处理和参数验证
+ /// 设置消息处理器
///
- /// 消息名称数组,对应原始方法中的names参数
- /// 消息处理器,对应原始方法中的handler参数
public void SetMessageHandler(string[] names, MessageHandler handler)
{
ThrowIfDisposed();
@@ -358,24 +193,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 取消设置消息处理器 - 对应LTEClientWebSocket.UnsetMessageHandler()方法
- ///
- /// 功能说明:
- /// 1. 取消按名称的消息处理器,对应原始UnsetMessageHandler()方法的核心逻辑
- /// 2. 委托给MessageIdManager处理,提供统一的消息处理器管理
- /// 3. 支持多个消息名称的处理器取消
- ///
- /// 详细对应关系:
- /// - 参数names:对应原始方法中的names参数,消息名称数组
- /// - 处理器移除:对应原始的_messageHandlersByName移除逻辑
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 委托给MessageIdManager,提供统一管理
- /// - 保持了完全一致的接口和功能
- /// - 更好的错误处理和参数验证
+ /// 取消设置消息处理器
///
- /// 消息名称数组,对应原始方法中的names参数
public void UnsetMessageHandler(string[] names)
{
ThrowIfDisposed();
@@ -383,25 +202,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 检查是否为当前日志获取消息 - 对应LTEClientWebSocket中的_logGetId检查逻辑
- ///
- /// 功能说明:
- /// 1. 检查指定的消息ID是否为当前的日志获取消息ID
- /// 2. 委托给MessageIdManager处理,提供统一的LogGet ID管理
- /// 3. 用于日志获取流程的状态检查
- ///
- /// 详细对应关系:
- /// - 参数messageId:对应原始实现中的消息ID检查
- /// - 返回值:true表示是当前LogGet消息,false表示不是,对应原始逻辑
- /// - 检查逻辑:对应原始的_logGetId比较逻辑
- ///
- /// 重构改进:
- /// - 委托给MessageIdManager,提供统一管理
- /// - 保持了完全一致的检查逻辑
- /// - 更好的线程安全性
+ /// 检查是否为当前日志获取消息
///
- /// 要检查的消息ID
- /// 是否为当前日志获取消息
public bool IsCurrentLogGetMessage(long messageId)
{
ThrowIfDisposed();
@@ -409,22 +211,7 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 重置日志获取ID - 对应LTEClientWebSocket中的_logGetId重置逻辑
- ///
- /// 功能说明:
- /// 1. 重置日志获取消息ID,对应原始实现中的_logGetId重置逻辑
- /// 2. 委托给MessageIdManager处理,提供统一的LogGet ID管理
- /// 3. 用于日志获取流程的重置操作
- ///
- /// 详细对应关系:
- /// - 重置逻辑:对应原始的_logGetId = -1操作
- /// - 日志记录:对应原始实现中的日志记录
- /// - 事件触发:对应原始实现中的状态变化通知
- ///
- /// 重构改进:
- /// - 委托给MessageIdManager,提供统一管理
- /// - 保持了完全一致的重置逻辑
- /// - 更好的事件通知机制
+ /// 重置日志获取ID
///
public void ResetLogGetId()
{
@@ -433,24 +220,8 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
}
///
- /// 清理过期的消息处理器 - 对应LTEClientWebSocket中的处理器清理逻辑
- ///
- /// 功能说明:
- /// 1. 清理过期的消息处理器,防止内存泄漏
- /// 2. 委托给MessageIdManager处理,提供统一的处理器管理
- /// 3. 支持可配置的过期时间
- ///
- /// 详细对应关系:
- /// - 参数maxAge:对应原始实现中的过期时间配置
- /// - 清理逻辑:对应原始的处理器清理逻辑
- /// - 日志记录:对应原始实现中的日志记录
- ///
- /// 重构改进:
- /// - 委托给MessageIdManager,提供统一管理
- /// - 保持了完全一致的清理逻辑
- /// - 更好的内存管理
+ /// 清理过期的消息处理器
///
- /// 最大存活时间(毫秒),默认30000毫秒
public void CleanupExpiredHandlers(int maxAge = 30000)
{
ThrowIfDisposed();
diff --git a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/WebSocketMessageManager.cs b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/WebSocketMessageManager.cs
index 0bef973..44c7657 100644
--- a/CoreAgent.ProtocolClient/Managers/WebSocketMgr/WebSocketMessageManager.cs
+++ b/CoreAgent.ProtocolClient/Managers/WebSocketMgr/WebSocketMessageManager.cs
@@ -12,331 +12,53 @@ using WebSocket4Net;
namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
{
///
- /// WebSocket消息管理器 - 专门处理WebSocket的收发业务
- ///
- /// 重构说明:
- /// 1. 对应LTEClientWebSocket中的WebSocket连接和消息传输功能
- /// 2. 集成MessageIdManager统一管理消息ID和回调
- /// 3. 移除_sentMessages和_receivedMessages消息缓存,专注传输
- /// 4. 移除业务逻辑功能(统计更新、日志解析等),实现职责分离
- ///
- /// 主要功能:
- /// - WebSocket连接管理(对应LTEClientWebSocket.Start()和Stop())
- /// - 消息发送和接收(对应LTEClientWebSocket.SendMessage()和OnSocketMessage())
- /// - 消息队列和批量发送(对应LTEClientWebSocket._messageFifo和SendMessageNow())
- /// - 事件通知(对应LTEClientWebSocket的事件系统)
- ///
- /// 与LTEClientWebSocket的详细对应关系:
- ///
- /// 1. 连接管理对应关系:
- /// - Connect() 对应 Start() 方法中的WebSocket连接建立逻辑
- /// - Disconnect() 对应 Stop() 方法中的WebSocket关闭逻辑
- /// - OnSocketOpened/OnSocketClosed/OnSocketError 对应原始的事件处理器
- ///
- /// 2. 消息发送对应关系:
- /// - SendMessage() 对应 SendMessage() 方法的核心逻辑
- /// - SendLogGetMessage() 对应 LogGet() 方法中的消息发送部分
- /// - _messageFifo 对应原始的 _messageFifo 队列
- /// - SendMessageNow() 对应原始的 SendMessageNow() 方法
- /// - StartMessageDeferTimer() 对应原始的定时器启动逻辑
- ///
- /// 3. 消息接收对应关系:
- /// - OnSocketMessageReceived() 对应 OnSocketMessage() 方法
- /// - HandleReceivedMessage() 对应 OnSocketMessage() 中的消息处理逻辑
- /// - MessageReceived 事件对应原始的 MessageReceived 事件
- ///
- /// 4. 消息ID管理对应关系:
- /// - MessageIdManager 替代原始的 _messageId 和 _logGetId 字段
- /// - GenerateGeneralMessageId() 对应 Interlocked.Increment(ref _messageId)
- /// - GenerateLogGetMessageId() 对应 _logGetId 的管理逻辑
- ///
- /// 5. 事件系统对应关系:
- /// - ConnectionOpened 对应原始的 ConnectionOpened 事件
- /// - ConnectionClosed 对应原始的 ConnectionClosed 事件
- /// - ConnectionError 对应原始的 ConnectionError 事件
- /// - MessageReceived 对应原始的 MessageReceived 事件
- /// - MessageSent 新增事件,提供更完整的消息生命周期通知
- ///
- /// 6. 资源管理对应关系:
- /// - Dispose() 对应原始的 Dispose() 方法
- /// - _disposed 字段对应原始的 _disposed 字段
- /// - 定时器管理对应原始的定时器清理逻辑
- ///
- /// 重构优势:
- /// 1. 职责分离:专注WebSocket传输,移除业务逻辑
- /// 2. 代码复用:可在多个地方复用WebSocket管理器
- /// 3. 测试友好:更容易进行单元测试
- /// 4. 维护简单:更清晰的代码结构
- /// 5. 功能增强:通过MessageIdManager提供更好的消息管理
+ /// WebSocket消息管理器 - 处理WebSocket连接和消息传输
///
public partial class WebSocketMessageManager : IDisposable
{
#region 私有字段
- ///
- /// WebSocket实例 - 对应LTEClientWebSocket._webSocket
- /// 负责底层的WebSocket连接和通信
- ///
- /// 对应关系:
- /// - 创建:Connect()方法中创建,对应Start()方法中的_webSocket = new WebSocket(url)
- /// - 配置:EnableAutoSendPing = false,对应原始实现
- /// - 事件绑定:绑定Opened/Closed/MessageReceived/Error事件,对应原始事件绑定
- /// - 连接:调用Open()方法,对应原始的_webSocket.Open()
- /// - 关闭:调用Close()方法,对应原始的_webSocket.Close()
- /// - 清理:在Disconnect()中设置为null,对应原始的资源清理
- ///
+ // WebSocket连接实例
private WebSocket? _webSocket;
- ///
- /// 消息ID管理器 - 对应LTEClientWebSocket._messageId和_logGetId
- /// 统一管理通用消息ID和日志获取消息ID,提供更好的消息跟踪和回调管理
- ///
- /// 对应关系:
- /// - _messageId 对应 MessageIdManager.GenerateGeneralMessageId()
- /// - _logGetId 对应 MessageIdManager.GenerateLogGetMessageId()
- /// - _messageHandlers 对应 MessageIdManager的内部处理器管理
- /// - _messageHandlersByName 对应 MessageIdManager的按名称处理器管理
- ///
- /// 功能增强:
- /// - 线程安全的ID生成,替代原始的Interlocked.Increment
- /// - 统一的处理器管理,提供更好的回调跟踪
- /// - 自动清理过期处理器,防止内存泄漏
- /// - 事件通知机制,提供ID变化通知
- ///
- private readonly MessageIdManager _messageIdManager;
+ // 客户端名称
+ private readonly string _clientName;
- ///
- /// 日志记录器 - 对应LTEClientWebSocket._logger
- /// 用于记录WebSocket操作和错误信息
- ///
- /// 对应关系:
- /// - 构造函数参数:对应LTEClientWebSocket构造函数中的logger参数
- /// - 日志记录:对应原始实现中的所有_logger.LogXXX调用
- /// - 日志格式:保持与原始实现一致的日志格式
- ///
- /// 功能增强:
- /// - 更详细的错误日志记录
- /// - 更好的异常堆栈跟踪
- /// - 统一的日志格式和级别
- ///
- private readonly ILogger _logger;
+ // 日志记录器
+ private readonly ILogger _logger;
- ///
- /// 客户端名称 - 对应LTEClientWebSocket._config.Name
- /// 用于日志记录和事件标识
- ///
- /// 对应关系:
- /// - 构造函数参数:对应LTEClientWebSocket构造函数中的config.Name
- /// - 日志前缀:对应原始实现中所有日志的[{_config.Name}]前缀
- /// - 事件标识:用于区分不同客户端的事件
- ///
- /// 功能增强:
- /// - 参数验证:确保clientName不为null
- /// - 统一标识:在所有日志和事件中使用一致的客户端标识
- ///
- private readonly string _clientName;
+ // 消息ID管理器
+ private readonly MessageIdManager _messageIdManager;
- ///
- /// 消息队列 - 对应LTEClientWebSocket._messageFifo
- /// 线程安全的阻塞集合,用于批量发送优化
- /// 优化说明:从ConcurrentQueue改为BlockingCollection,提供更好的线程安全性和阻塞能力
- ///
- /// 对应关系:
- /// - 队列类型:BlockingCollection,优化后的线程安全集合
- /// - 入队操作:Add(message),对应原始的_messageFifo.Enqueue(message)
- /// - 出队操作:TryTake(out message),对应原始的队列处理逻辑
- /// - 批量处理:支持批量消息发送,对应原始的批处理逻辑
- ///
- /// 功能增强:
- /// - 线程安全:使用BlockingCollection保证线程安全
- /// - 阻塞能力:支持阻塞式出队操作,提高性能
- /// - 批量优化:支持批量发送减少网络开销
- /// - 延迟发送:配合_messageDeferTimer实现延迟发送
- /// - 资源管理:自动处理集合的完成状态
- ///
- /// 重构改进:
- /// - 移除了消息缓存功能,专注传输
- /// - 优化了队列操作逻辑,提供更好的性能
- /// - 增强了线程安全性和资源管理
- ///
+ // 消息队列
private readonly BlockingCollection _messageFifo;
- ///
- /// 消息延迟发送定时器 - 对应LTEClientWebSocket._messageDeferTimer
- /// 用于实现消息的批量发送和延迟发送机制
- /// 保持与原始实现完全一致的逻辑
- ///
- /// 对应关系:
- /// - 定时器类型:Timer,与原始实现完全一致
- /// - 启动逻辑:StartMessageDeferTimer(),对应原始的定时器启动
- /// - 停止逻辑:StopMessageDeferTimer(),对应原始的定时器停止
- /// - 延迟策略:1毫秒延迟,与原始实现完全一致
- /// - 批处理大小:100条消息,与原始实现完全一致
- ///
- /// 功能保持:
- /// - 批量发送:当队列中消息少于100条时,延迟1毫秒发送
- /// - 立即发送:当队列中消息达到100条时,立即发送
- /// - 资源管理:在Disconnect()和Dispose()中正确释放
- ///
- /// 重构改进:
- /// - 更清晰的定时器管理逻辑
- /// - 更好的异常处理
- /// - 保持了完全一致的批处理策略
- ///
+ // 消息延迟发送定时器
private Timer? _messageDeferTimer;
- ///
- /// 释放标志 - 对应LTEClientWebSocket._disposed
- /// 防止重复释放和已释放对象的操作
- ///
- /// 对应关系:
- /// - 字段类型:bool,对应原始的_disposed字段
- /// - 返回值:true表示已释放,false表示未释放,对应原始实现
- /// - 使用场景:外部检查对象释放状态,对应原始实现
- /// - 线程安全:直接返回_disposed字段值,对应原始实现
- ///
- /// 功能保持:
- /// - 释放状态检查:外部可以检查对象是否已释放
- /// - 资源保护:防止对已释放对象的操作
- /// - 状态查询:提供对象状态的查询接口
- ///
- /// 重构改进:
- /// - 保持了完全一致的检查逻辑
- /// - 保持了完全一致的返回值语义
- /// - 保持了完全一致的使用场景
- ///
+ // 释放标志
private bool _disposed;
- ///
- /// 同步锁对象
- /// 用于确保线程安全的操作
- ///
- /// 对应关系:
- /// - 新增功能:原始实现中没有显式的同步锁
- /// - 用途:确保关键操作的线程安全
- /// - 使用场景:在需要线程安全的地方使用lock语句
- ///
- /// 功能增强:
- /// - 线程安全:确保关键操作的原子性
- /// - 死锁预防:使用细粒度锁避免死锁
- /// - 性能优化:最小化锁的持有时间
- ///
+ // 同步锁对象
private readonly object _lockObject = new object();
#endregion
#region 事件
- ///
- /// 连接打开事件 - 对应LTEClientWebSocket.ConnectionOpened
- /// 当WebSocket连接成功建立时触发
- ///
- /// 对应关系:
- /// - 事件类型:EventHandler,与原始实现完全一致
- /// - 触发时机:在OnSocketOpened()中触发,对应原始的OnSocketOpened事件处理
- /// - 触发条件:WebSocket连接成功建立时
- /// - 事件参数:无参数,与原始实现完全一致
- ///
- /// 功能保持:
- /// - 连接状态通知:通知外部连接已建立
- /// - 事件订阅:支持多个订阅者
- /// - 异步触发:事件触发不会阻塞WebSocket操作
- ///
- /// 重构改进:
- /// - 更清晰的触发时机
- /// - 更好的错误处理
- /// - 保持了完全一致的事件接口
- ///
+ // 连接打开事件
public event EventHandler? ConnectionOpened;
- ///
- /// 连接关闭事件 - 对应LTEClientWebSocket.ConnectionClosed
- /// 当WebSocket连接关闭时触发
- ///
- /// 对应关系:
- /// - 事件类型:EventHandler,与原始实现完全一致
- /// - 触发时机:在OnSocketClosed()中触发,对应原始的OnSocketClosed事件处理
- /// - 触发条件:WebSocket连接关闭时
- /// - 事件参数:无参数,与原始实现完全一致
- ///
- /// 功能保持:
- /// - 连接状态通知:通知外部连接已关闭
- /// - 事件订阅:支持多个订阅者
- /// - 异步触发:事件触发不会阻塞WebSocket操作
- ///
- /// 重构改进:
- /// - 更清晰的触发时机
- /// - 更好的资源清理
- /// - 保持了完全一致的事件接口
- ///
+ // 连接关闭事件
public event EventHandler? ConnectionClosed;
- ///
- /// 连接错误事件 - 对应LTEClientWebSocket.ConnectionError
- /// 当WebSocket连接发生错误时触发
- ///
- /// 对应关系:
- /// - 事件类型:EventHandler,与原始实现完全一致
- /// - 触发时机:在OnSocketError()和异常处理中触发,对应原始的错误处理
- /// - 触发条件:WebSocket连接错误、消息处理错误等
- /// - 事件参数:错误信息字符串,与原始实现完全一致
- ///
- /// 功能保持:
- /// - 错误通知:通知外部连接或处理错误
- /// - 事件订阅:支持多个订阅者
- /// - 异步触发:事件触发不会阻塞WebSocket操作
- ///
- /// 重构改进:
- /// - 更详细的错误信息
- /// - 更好的异常处理
- /// - 保持了完全一致的事件接口
- ///
+ // 连接错误事件
public event EventHandler? ConnectionError;
- ///
- /// 消息接收事件 - 对应LTEClientWebSocket.MessageReceived
- /// 当接收到WebSocket消息时触发
- ///
- /// 对应关系:
- /// - 事件类型:EventHandler,与原始实现完全一致
- /// - 触发时机:在OnSocketMessageReceived()中触发,对应原始的OnSocketMessage事件处理
- /// - 触发条件:接收到WebSocket消息并解析成功后
- /// - 事件参数:解析后的JObject消息,与原始实现完全一致
- ///
- /// 功能保持:
- /// - 消息通知:通知外部接收到新消息
- /// - 事件订阅:支持多个订阅者
- /// - 异步触发:事件触发不会阻塞消息处理
- /// - 触发顺序:在消息处理开始时就触发,与原始实现完全一致
- ///
- /// 重构改进:
- /// - 更清晰的触发时机
- /// - 更好的消息解析
- /// - 保持了完全一致的事件接口和触发顺序
- ///
+ // 消息接收事件
public event EventHandler? MessageReceived;
- ///
- /// 消息发送事件 - 新增功能,LTEClientWebSocket中没有对应事件
- /// 当消息成功发送时触发,提供更完整的消息生命周期通知
- ///
- /// 对应关系:
- /// - 事件类型:EventHandler,与MessageReceived保持一致
- /// - 触发时机:在SendMessageNow()中触发,对应消息发送成功时
- /// - 触发条件:消息成功发送到WebSocket时
- /// - 事件参数:发送的JObject消息,与MessageReceived保持一致
- ///
- /// 功能增强:
- /// - 消息生命周期:提供完整的消息发送通知
- /// - 调试支持:便于调试消息发送流程
- /// - 监控支持:便于监控消息发送状态
- /// - 事件订阅:支持多个订阅者
- ///
- /// 重构优势:
- /// - 更完整的消息生命周期管理
- /// - 更好的调试和监控支持
- /// - 与MessageReceived事件形成对称的事件系统
- ///
+ // 消息发送事件
public event EventHandler? MessageSent;
#endregion
@@ -344,113 +66,27 @@ namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
#region 属性
///
- /// 是否已连接 - 对应LTEClientWebSocket.IsConnected
- /// 检查WebSocket连接状态
- ///
- /// 对应关系:
- /// - 属性类型:bool,与原始实现完全一致
- /// - 检查逻辑:_webSocket?.State == WebSocketState.Open,与原始实现完全一致
- /// - 使用场景:在SendMessage()中检查连接状态,对应原始实现
- /// - 返回值:true表示已连接,false表示未连接,与原始实现完全一致
- ///
- /// 功能保持:
- /// - 连接状态检查:快速检查WebSocket连接状态
- /// - 空安全:使用?.操作符避免空引用异常
- /// - 实时状态:反映WebSocket的实时连接状态
- ///
- /// 重构改进:
- /// - 保持了完全一致的检查逻辑
- /// - 保持了完全一致的返回值语义
- /// - 保持了完全一致的使用场景
+ /// 是否已连接
///
public bool IsConnected => _webSocket?.State == WebSocketState.Open;
///
- /// WebSocket状态 - 对应LTEClientWebSocket._webSocket?.State
- /// 获取详细的WebSocket连接状态
- ///
- /// 对应关系:
- /// - 属性类型:WebSocketState,对应原始的_webSocket?.State
- /// - 返回值:WebSocket的详细状态,对应原始实现
- /// - 空安全:使用??操作符提供默认值,对应原始实现
- /// - 使用场景:提供更详细的连接状态信息
- ///
- /// 功能保持:
- /// - 详细状态:提供WebSocket的详细连接状态
- /// - 空安全:当_webSocket为null时返回WebSocketState.None
- /// - 实时状态:反映WebSocket的实时状态
- ///
- /// 重构改进:
- /// - 保持了完全一致的状态获取逻辑
- /// - 保持了完全一致的默认值处理
- /// - 保持了完全一致的使用场景
+ /// WebSocket状态
///
public WebSocketState State => _webSocket?.State ?? WebSocketState.None;
///
- /// 是否已释放 - 对应LTEClientWebSocket._disposed
- /// 检查对象是否已被释放
- ///
- /// 对应关系:
- /// - 属性类型:bool,对应原始的_disposed字段
- /// - 返回值:true表示已释放,false表示未释放,对应原始实现
- /// - 使用场景:外部检查对象释放状态,对应原始实现
- /// - 线程安全:直接返回_disposed字段值,对应原始实现
- ///
- /// 功能保持:
- /// - 释放状态检查:外部可以检查对象是否已释放
- /// - 资源保护:防止对已释放对象的操作
- /// - 状态查询:提供对象状态的查询接口
- ///
- /// 重构改进:
- /// - 保持了完全一致的检查逻辑
- /// - 保持了完全一致的返回值语义
- /// - 保持了完全一致的使用场景
+ /// 是否已释放
///
public bool IsDisposed => _disposed;
///
- /// 消息队列数量 - 对应LTEClientWebSocket._messageFifo.Count
- /// 获取当前待发送消息的数量
- ///
- /// 对应关系:
- /// - 属性类型:int,对应原始的_messageFifo.Count
- /// - 返回值:队列中待发送消息的数量,对应原始实现
- /// - 使用场景:监控消息队列状态,对应原始实现
- /// - 线程安全:BlockingCollection.Count是线程安全的,对应原始实现
- ///
- /// 功能保持:
- /// - 队列监控:监控当前待发送消息的数量
- /// - 性能监控:便于监控消息发送性能
- /// - 调试支持:便于调试消息队列状态
- ///
- /// 重构改进:
- /// - 保持了完全一致的计数逻辑
- /// - 保持了完全一致的返回值语义
- /// - 保持了完全一致的使用场景
- /// - 优化:使用BlockingCollection提供更好的线程安全性
+ /// 消息队列数量
///
public int MessageQueueCount => _messageFifo.Count;
///
- /// 消息ID管理器 - 提供对MessageIdManager的访问
- /// 允许外部访问消息ID管理功能
- ///
- /// 对应关系:
- /// - 属性类型:MessageIdManager,对应原始的_messageId和_logGetId管理
- /// - 返回值:内部的消息ID管理器实例,对应原始实现
- /// - 使用场景:外部访问消息ID管理功能,对应原始实现
- /// - 封装性:提供对内部MessageIdManager的访问,对应原始实现
- ///
- /// 功能保持:
- /// - 功能访问:外部可以访问消息ID管理功能
- /// - 封装性:保持内部实现的封装性
- /// - 扩展性:支持外部扩展消息ID管理功能
- ///
- /// 重构改进:
- /// - 更统一的消息ID管理接口
- /// - 更好的功能封装
- /// - 保持了完全一致的功能访问方式
+ /// 消息ID管理器
///
public MessageIdManager MessageIdManager => _messageIdManager;
diff --git a/CoreAgent.ProtocolClient/Models/ProtocolLog.cs b/CoreAgent.ProtocolClient/Models/BuildProtocolLog.cs
similarity index 89%
rename from CoreAgent.ProtocolClient/Models/ProtocolLog.cs
rename to CoreAgent.ProtocolClient/Models/BuildProtocolLog.cs
index 50a536d..d6da262 100644
--- a/CoreAgent.ProtocolClient/Models/ProtocolLog.cs
+++ b/CoreAgent.ProtocolClient/Models/BuildProtocolLog.cs
@@ -7,7 +7,10 @@ using System.Threading.Tasks;
namespace CoreAgent.ProtocolClient.Models
{
- public class ProtocolLog
+ ///
+ /// 构建协议日志模型
+ ///
+ public class BuildProtocolLog
{
#region 基础属性
///
@@ -65,20 +68,20 @@ namespace CoreAgent.ProtocolClient.Models
#endregion
#region PHY层相关属性
- public PhyFields Phy { get; set; } = new();
+ public PhyLayerFields Phy { get; set; } = new();
#endregion
#region 数据相关属性
- public DataFields DataInfo { get; set; } = new();
+ public DataLayerFields DataInfo { get; set; } = new();
#endregion
#region MAC层相关属性
- public MacFields Mac { get; set; } = new();
+ public MacLayerFields Mac { get; set; } = new();
#endregion
}
// PHY层分组
- public class PhyFields
+ public class PhyLayerFields
{
///
/// 物理信道类型
@@ -135,7 +138,7 @@ namespace CoreAgent.ProtocolClient.Models
}
// 数据相关分组
- public class DataFields
+ public class DataLayerFields
{
///
/// IP长度
@@ -156,7 +159,7 @@ namespace CoreAgent.ProtocolClient.Models
}
// MAC层分组
- public class MacFields
+ public class MacLayerFields
{
///
/// 功率余量报告(PHR)
@@ -194,17 +197,17 @@ namespace CoreAgent.ProtocolClient.Models
///
- /// ProtocolLog扩展方法类
- /// 提供ProtocolLog相关的工具方法和扩展功能
+ /// BuildProtocolLog扩展方法类
+ /// 提供BuildProtocolLog相关的工具方法和扩展功能
///
- public static class ProtocolLogExtensions
+ public static class BuildProtocolLogExtensions
{
///
/// 获取协议日志数据的字符串表示
///
/// 协议日志对象
/// 格式化的日志数据字符串
- public static string GetProtocolLogData(this ProtocolLog log)
+ public static string GetProtocolLogData(this BuildProtocolLog log)
{
return string.Join("\n", log.Data);
}
diff --git a/CoreAgent.ProtocolClient/Models/ProtocolLogJson.cs b/CoreAgent.ProtocolClient/Models/SourceProtocolLog.cs
similarity index 82%
rename from CoreAgent.ProtocolClient/Models/ProtocolLogJson.cs
rename to CoreAgent.ProtocolClient/Models/SourceProtocolLog.cs
index 7d6c0bc..6b82b89 100644
--- a/CoreAgent.ProtocolClient/Models/ProtocolLogJson.cs
+++ b/CoreAgent.ProtocolClient/Models/SourceProtocolLog.cs
@@ -8,7 +8,10 @@ using System.Threading.Tasks;
namespace CoreAgent.ProtocolClient.Models
{
- public record class ProtocolLogJson
+ ///
+ /// 源协议日志模型
+ ///
+ public record class SourceProtocolLog
{
///
/// 消息ID
@@ -41,17 +44,9 @@ namespace CoreAgent.ProtocolClient.Models
public JToken? Logs { get; set; }
///
- /// 初始化协议日志实体类的新实例
+ /// 初始化源协议日志的新实例
///
- /// 消息内容
- /// 消息类型
- /// 协议版本
- /// 时间戳
- /// UTC时间戳
- /// 日志明细
- /// 消息ID
- /// 消息头信息
- public ProtocolLogJson(
+ public SourceProtocolLog(
string message,
string? type,
string? version,
@@ -71,9 +66,9 @@ namespace CoreAgent.ProtocolClient.Models
///
- /// 协议日志明细
+ /// 源协议日志明细模型
///
- public class ProtocolLogDetailJson
+ public class SourceProtocolLogDetail
{
///
/// 源信息
@@ -153,15 +148,14 @@ namespace CoreAgent.ProtocolClient.Models
[JsonProperty("rnti")]
public int? Rnti { get; set; }
-
///
/// 深拷贝当前对象
///
- public ProtocolLogDetailJson DeepClone()
+ public SourceProtocolLogDetail DeepClone()
{
// 通过序列化和反序列化实现深拷贝
var json = JsonConvert.SerializeObject(this);
- return JsonConvert.DeserializeObject(json)
+ return JsonConvert.DeserializeObject(json)
?? throw new InvalidOperationException("深拷贝失败,反序列化结果为 null");
}
}
diff --git a/CoreAgent.ProtocolClient/Models/TmsiMatchProcessor.cs b/CoreAgent.ProtocolClient/Models/TmsiMatchProcessor.cs
index 65c2879..b2b9768 100644
--- a/CoreAgent.ProtocolClient/Models/TmsiMatchProcessor.cs
+++ b/CoreAgent.ProtocolClient/Models/TmsiMatchProcessor.cs
@@ -64,7 +64,7 @@ namespace CoreAgent.ProtocolClient.Models
{
// 从UE链中获取IMSI
string imsi = GetImsiFromUeChain(receiveUeId, ueChains);
-
+
// 创建匹配结果
var matchResult = new TmsiMatchResult(tmsi, requestUeId, receiveUeId, imsi);
matches.Add(matchResult);
@@ -85,7 +85,7 @@ namespace CoreAgent.ProtocolClient.Models
var processedUeIds = new HashSet();
// 遍历所有TMSI匹配关系,构建链式结构
- foreach (var requestKvp in _tmsiToUeId)
+ foreach (var requestKvp in _tmsiToUeId)
{
uint tmsi = requestKvp.Key;
int requestUeId = requestKvp.Value;
@@ -101,7 +101,7 @@ namespace CoreAgent.ProtocolClient.Models
// 使用链的根节点(最外层节点)作为键
int rootUeId = chain[0];
ueChains[rootUeId] = chain;
-
+
// 标记所有UE ID为已处理
foreach (int ueId in chain)
{
@@ -205,7 +205,7 @@ namespace CoreAgent.ProtocolClient.Models
return imsiMapping.Key;
}
}
-
+
// 2. 如果当前UE ID没有IMSI,查找整个UE链中的IMSI
// 遍历所有IMSI映射,查找是否有任何UE ID对应的IMSI
foreach (var imsiMapping in _imsiToUeId)
@@ -215,7 +215,7 @@ namespace CoreAgent.ProtocolClient.Models
return imsiMapping.Key;
}
}
-
+
return string.Empty;
}
@@ -226,7 +226,7 @@ namespace CoreAgent.ProtocolClient.Models
public UeChainStats GetUeChainStats()
{
var ueChains = BuildUeChains();
-
+
return new UeChainStats
{
TotalChains = ueChains.Count,
@@ -321,4 +321,4 @@ namespace CoreAgent.ProtocolClient.Models
///
public string Imsi { get; set; } = string.Empty;
}
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/CoreAgent.ProtocolClient/Models/TmsiMatchResult.cs b/CoreAgent.ProtocolClient/Models/TmsiMatchResult.cs
index 11d1ce6..5379289 100644
--- a/CoreAgent.ProtocolClient/Models/TmsiMatchResult.cs
+++ b/CoreAgent.ProtocolClient/Models/TmsiMatchResult.cs
@@ -53,4 +53,65 @@ namespace CoreAgent.ProtocolClient.Models
return $"TMSI: 0x{Tmsi:X8}, RequestUE: {RequestUeId}, ReceiveUE: {ReceiveUeId}{imsiInfo}";
}
}
-}
\ No newline at end of file
+
+ ///
+ /// Service Request TMSI映射实体
+ /// 用于平铺 SrTmsiToUeId 字典数据,包含 IMSI、TMSI、UE ID、Root UE ID 四个字段
+ ///
+ public class SrTmsiMapping
+ {
+ ///
+ /// IMSI标识符
+ ///
+ public string Imsi { get; set; } = string.Empty;
+
+ ///
+ /// Service Request TMSI标识符
+ ///
+ public uint Tmsi { get; set; }
+
+ ///
+ /// UE ID
+ ///
+ public int UeId { get; set; }
+
+ ///
+ /// Root UE ID(链的根节点)
+ ///
+ public int RootUeId { get; set; }
+
+ ///
+ /// PLMN标识符
+ ///
+ public string Plmn { get; set; } = string.Empty;
+
+ ///
+ /// 构造函数
+ ///
+ /// IMSI标识符
+ /// Service Request TMSI标识符
+ /// UE ID
+ /// Root UE ID
+ /// PLMN标识符
+ public SrTmsiMapping(string imsi, uint tmsi, int ueId, int rootUeId = 0, string plmn = "")
+ {
+ Imsi = imsi;
+ Tmsi = tmsi;
+ UeId = ueId;
+ RootUeId = rootUeId;
+ Plmn = plmn;
+ }
+
+ ///
+ /// 重写ToString方法,提供友好的字符串表示
+ ///
+ /// 格式化的字符串
+ public override string ToString()
+ {
+ var imsiInfo = string.IsNullOrEmpty(Imsi) ? "" : $", IMSI: {Imsi}";
+ var rootInfo = RootUeId > 0 ? $", Root UE: {RootUeId}" : "";
+ var plmnInfo = string.IsNullOrEmpty(Plmn) ? "" : $", PLMN: {Plmn}";
+ return $"SR-TMSI: 0x{Tmsi:X8}, UE ID: {UeId}{imsiInfo}{rootInfo}{plmnInfo}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.ProtocolClient/Models/ProtocolLogDetail.cs b/CoreAgent.ProtocolClient/Models/TransferProtocolLog.cs
similarity index 95%
rename from CoreAgent.ProtocolClient/Models/ProtocolLogDetail.cs
rename to CoreAgent.ProtocolClient/Models/TransferProtocolLog.cs
index 895a304..5dc754c 100644
--- a/CoreAgent.ProtocolClient/Models/ProtocolLogDetail.cs
+++ b/CoreAgent.ProtocolClient/Models/TransferProtocolLog.cs
@@ -5,11 +5,11 @@ using CoreAgent.ProtocolClient.Enums;
namespace CoreAgent.ProtocolClient.Models
{
///
- /// 协议日志详情实体
- /// 用于存储解析后的协议日志详细信息到数据库
+ /// 传输协议日志模型
+ /// 用于传输给上层的协议日志数据
///
[Table("ProtocolLogDetails")]
- public class ProtocolLogDetail
+ public class TransferProtocolLog
{
///
/// 主键ID
diff --git a/CoreAgent.ProtocolClient/Models/UeInfo.cs b/CoreAgent.ProtocolClient/Models/UeInfo.cs
index f6e6a41..8c81d82 100644
--- a/CoreAgent.ProtocolClient/Models/UeInfo.cs
+++ b/CoreAgent.ProtocolClient/Models/UeInfo.cs
@@ -10,7 +10,7 @@ namespace CoreAgent.ProtocolClient.Models
/// 用户设备(UE)信息模型
/// 用于存储用户设备的基本信息,包括标识符、设备能力等
///
- public class UeInfo
+ public class UEInfo
{
///
/// 用户设备唯一标识符
diff --git a/CoreAgent.ProtocolClient/modify.md b/CoreAgent.ProtocolClient/modify.md
index 8e8c6d2..a2be3c9 100644
--- a/CoreAgent.ProtocolClient/modify.md
+++ b/CoreAgent.ProtocolClient/modify.md
@@ -195,4 +195,1129 @@ public static class ProtocolCapsExtensions
6. **其他辅助方法** - 完善了消息处理器管理和清理相关方法
**提交信息:** 重构WebSocket消息管理器:完善PublicMethods.cs文档和实现
-**提交哈希:** 219118d
\ No newline at end of file
+**提交哈希:** 219118d
+
+## 2024-12-19
+### 优化Constructor.cs注释和修复字段声明顺序
+
+**修改内容:**
+1. **Constructor.cs注释优化**
+ - 简化了构造函数注释,提高可读性
+ - 移除了冗余的详细说明,保留核心要点
+ - 优化了参数和异常说明的表述
+
+2. **WebSocketMessageManager.cs字段顺序修复**
+ - 修复了字段声明顺序问题
+ - 将`_clientName`字段移到`_logger`字段之前
+ - 确保字段声明顺序与构造函数中的使用顺序一致
+
+**涉及文件:**
+- `Managers/WebSocketMgr/Constructor.cs` - 优化注释,提高可读性
+- `Managers/WebSocketMgr/WebSocketMessageManager.cs` - 修复字段声明顺序
+
+**主要改进:**
+1. **注释优化**
+ - 简化了XML文档注释,去除冗余信息
+ - 保留了核心功能说明和参数描述
+ - 提高了代码的可读性和维护性
+
+2. **字段顺序修复**
+ - 修复了潜在的初始化顺序问题
+ - 确保字段声明顺序与使用顺序一致
+ - 提高了代码的逻辑性和可读性
+
+**提交信息:** 优化Constructor.cs注释和修复字段声明顺序
+
+## 2024-12-19
+### 大幅优化注释,提高代码可读性
+
+**修改内容:**
+1. **Constructor.cs注释优化**
+ - 完全移除了XML文档注释,保留简洁的行内注释
+ - 简化了所有注释内容,只保留核心要点
+ - 提高了代码的可读性和简洁性
+
+2. **WebSocketMessageManager.cs注释大幅简化**
+ - 简化了类级别的XML文档注释,从冗长的重构说明简化为一行描述
+ - 将所有字段的详细XML文档注释改为简洁的行内注释
+ - 将所有事件的详细XML文档注释改为简洁的行内注释
+ - 保持了代码的功能性,但大幅提高了可读性
+
+**涉及文件:**
+- `Managers/WebSocketMgr/Constructor.cs` - 完全简化注释
+- `Managers/WebSocketMgr/WebSocketMessageManager.cs` - 大幅简化所有注释
+
+**主要改进:**
+1. **注释风格统一**
+ - 统一使用简洁的行内注释风格
+ - 移除了冗余的XML文档注释
+ - 保持了注释的核心信息
+
+2. **可读性大幅提升**
+ - 代码更加简洁明了
+ - 减少了视觉干扰
+ - 提高了代码扫描效率
+
+3. **维护性改进**
+ - 减少了注释维护的工作量
+ - 降低了注释过时的风险
+ - 提高了代码的实用性
+
+**示例对比:**
+```csharp
+// 优化前:冗长的XML文档注释
+///
+/// WebSocket消息管理器 - 专门处理WebSocket的收发业务
+/// 重构说明:1. 对应LTEClientWebSocket中的WebSocket连接和消息传输功能...
+///
+
+// 优化后:简洁的XML文档注释
+///
+/// WebSocket消息管理器 - 处理WebSocket连接和消息传输
+///
+
+// 优化前:详细的字段注释
+///
+/// WebSocket实例 - 对应LTEClientWebSocket._webSocket...
+///
+
+// 优化后:简洁的行内注释
+// WebSocket连接实例
+```
+
+**提交信息:** 大幅优化注释,提高代码可读性
+
+## 2024-12-19
+### 优化PublicMethods.cs注释,完成WebSocket管理器注释简化
+
+**修改内容:**
+1. **PublicMethods.cs注释大幅简化**
+ - 简化了所有方法的XML文档注释,从冗长的重构说明简化为一行描述
+ - 移除了所有详细的参数说明和返回值描述
+ - 简化了所有行内注释,去除冗余的对应关系说明
+ - 保持了代码的功能性,但大幅提高了可读性
+
+**涉及文件:**
+- `Managers/WebSocketMgr/PublicMethods.cs` - 大幅简化所有方法注释
+
+**主要改进:**
+1. **方法注释简化**
+ - 所有方法的XML文档注释简化为一行描述
+ - 移除了冗长的功能说明、对应关系、重构改进等详细描述
+ - 移除了所有参数和返回值的详细说明
+
+2. **行内注释优化**
+ - 简化了所有行内注释,去除冗余的对应关系说明
+ - 保留了核心的功能描述
+ - 提高了代码的简洁性
+
+3. **可读性提升**
+ - 代码更加简洁明了
+ - 减少了视觉干扰
+ - 提高了代码扫描效率
+
+**示例对比:**
+```csharp
+// 优化前:冗长的方法注释
+///
+/// 连接到WebSocket服务器 - 对应LTEClientWebSocket.Start()方法
+/// 功能说明:1. 建立WebSocket连接,对应原始Start()方法的核心逻辑...
+///
+/// WebSocket URL,对应LTEClientWebSocket._config.Address
+
+// 优化后:简洁的方法注释
+///
+/// 连接到WebSocket服务器
+///
+
+// 优化前:详细的行内注释
+// 构建WebSocket URL - 对应原始实现中的URL构建逻辑
+
+// 优化后:简洁的行内注释
+// 构建WebSocket URL
+```
+
+**完成状态:**
+- ✅ Constructor.cs - 注释完全简化
+- ✅ WebSocketMessageManager.cs - 字段和事件注释简化
+- ✅ PublicMethods.cs - 方法注释简化
+- ✅ 所有WebSocket管理器相关文件的注释优化完成
+
+**提交信息:** 优化PublicMethods.cs注释,完成WebSocket管理器注释简化
+
+## 2024-12-19
+### 优化PrivateMethods.cs注释,完成所有WebSocket管理器文件注释简化
+
+**修改内容:**
+1. **PrivateMethods.cs注释大幅简化**
+ - 简化了所有私有方法的XML文档注释,从冗长的重构说明简化为一行描述
+ - 移除了所有详细的参数说明和功能描述
+ - 简化了所有行内注释,去除冗余的对应关系说明
+ - 保持了代码的功能性,但大幅提高了可读性
+
+**涉及文件:**
+- `Managers/WebSocketMgr/PrivateMethods.cs` - 大幅简化所有私有方法注释
+
+**主要改进:**
+1. **私有方法注释简化**
+ - 所有私有方法的XML文档注释简化为一行描述
+ - 移除了冗长的功能说明、对应关系、重构改进等详细描述
+ - 移除了所有参数和返回值的详细说明
+
+2. **行内注释优化**
+ - 简化了所有行内注释,去除冗余的对应关系说明
+ - 保留了核心的功能描述
+ - 提高了代码的简洁性
+
+3. **可读性提升**
+ - 代码更加简洁明了
+ - 减少了视觉干扰
+ - 提高了代码扫描效率
+
+**示例对比:**
+```csharp
+// 优化前:冗长的私有方法注释
+///
+/// WebSocket连接打开事件处理器 - 对应LTEClientWebSocket.OnSocketOpened
+/// 功能说明:1. 处理WebSocket连接成功建立事件...
+///
+/// 事件发送者
+
+// 优化后:简洁的私有方法注释
+///
+/// WebSocket连接打开事件处理器
+///
+
+// 优化前:详细的行内注释
+// 解析消息 - 对应原始实现中的消息解析逻辑
+
+// 优化后:简洁的行内注释
+// 解析消息
+```
+
+**完成状态:**
+- ✅ Constructor.cs - 注释完全简化
+- ✅ WebSocketMessageManager.cs - 字段和事件注释简化
+- ✅ PublicMethods.cs - 方法注释简化
+- ✅ PrivateMethods.cs - 私有方法注释简化
+- ✅ 所有WebSocket管理器相关文件的注释优化完成
+
+**提交信息:** 优化PrivateMethods.cs注释,完成所有WebSocket管理器文件注释简化
+
+## 2024-12-19
+### 优化Dispose.cs注释,完成WebSocket管理器所有文件注释简化
+
+**修改内容:**
+1. **Dispose.cs注释大幅简化**
+ - 简化了所有方法的XML文档注释,从冗长的重构说明简化为一行描述
+ - 移除了所有详细的参数说明和功能描述
+ - 简化了所有行内注释,去除冗余的对应关系说明
+ - 保持了代码的功能性,但大幅提高了可读性
+
+**涉及文件:**
+- `Managers/WebSocketMgr/Dispose.cs` - 大幅简化所有方法注释
+
+**主要改进:**
+1. **Dispose方法注释简化**
+ - 所有方法的XML文档注释简化为一行描述
+ - 移除了冗长的功能说明、对应关系、重构改进等详细描述
+ - 移除了所有参数和返回值的详细说明
+
+2. **行内注释优化**
+ - 简化了所有行内注释,去除冗余的对应关系说明
+ - 保留了核心的功能描述
+ - 提高了代码的简洁性
+
+3. **可读性提升**
+ - 代码更加简洁明了
+ - 减少了视觉干扰
+ - 提高了代码扫描效率
+
+**示例对比:**
+```csharp
+// 优化前:冗长的Dispose方法注释
+///
+/// 释放资源 - 对应LTEClientWebSocket.Dispose()方法
+/// 功能说明:1. 释放WebSocket连接和相关资源...
+///
+
+// 优化后:简洁的Dispose方法注释
+///
+/// 释放资源
+///
+
+// 优化前:详细的行内注释
+// 停止消息发送定时器 - 对应原始实现中的定时器释放
+
+// 优化后:简洁的行内注释
+// 停止消息发送定时器
+```
+
+**完成状态:**
+- ✅ Constructor.cs - 注释完全简化
+- ✅ WebSocketMessageManager.cs - 字段和事件注释简化
+- ✅ PublicMethods.cs - 公共方法注释简化
+- ✅ PrivateMethods.cs - 私有方法注释简化
+- ✅ Dispose.cs - Dispose方法注释简化
+- ✅ 所有WebSocket管理器相关文件的注释优化完成
+
+**提交信息:** 优化Dispose.cs注释,完成WebSocket管理器所有文件注释简化
+
+## 2024-12-19
+### 优化WebSocketMessageManager.cs属性注释,完成所有注释简化
+
+**修改内容:**
+1. **WebSocketMessageManager.cs属性注释简化**
+ - 简化了所有属性的XML文档注释,从冗长的重构说明简化为一行描述
+ - 移除了所有详细的对应关系说明和功能描述
+ - 保持了代码的功能性,但大幅提高了可读性
+
+**涉及文件:**
+- `Managers/WebSocketMgr/WebSocketMessageManager.cs` - 简化所有属性注释
+
+**主要改进:**
+1. **属性注释简化**
+ - 所有属性的XML文档注释简化为一行描述
+ - 移除了冗长的对应关系、功能保持、重构改进等详细描述
+ - 保持了简洁明了的功能说明
+
+2. **可读性提升**
+ - 代码更加简洁明了
+ - 减少了视觉干扰
+ - 提高了代码扫描效率
+
+**示例对比:**
+```csharp
+// 优化前:冗长的属性注释
+///
+/// 是否已连接 - 对应LTEClientWebSocket.IsConnected
+/// 检查WebSocket连接状态
+/// 对应关系:- 属性类型:bool,与原始实现完全一致...
+///
+
+// 优化后:简洁的属性注释
+///
+/// 是否已连接
+///
+```
+
+**完成状态:**
+- ✅ Constructor.cs - 注释完全简化
+- ✅ WebSocketMessageManager.cs - 字段、事件和属性注释简化
+- ✅ PublicMethods.cs - 公共方法注释简化
+- ✅ PrivateMethods.cs - 私有方法注释简化
+- ✅ Dispose.cs - Dispose方法注释简化
+- ✅ 所有WebSocket管理器相关文件的注释优化完成
+
+**提交信息:** 优化WebSocketMessageManager.cs属性注释,完成所有注释简化
+
+## 2024-12-19
+### 创建MessageIdManager.md文档文件
+
+**修改内容:**
+1. **创建MessageIdManager.md文档**
+ - 在Docs目录下创建了MessageIdManager.md文档文件
+ - 包含完整的MessageIdManager.cs代码和详细注释
+ - 添加了类概述、主要功能、设计改进和使用场景说明
+ - 遵循与Constructor.md相同的文档格式
+
+**涉及文件:**
+- `Docs/MessageIdManager.md` - 新创建的MessageIdManager文档
+
+**文档内容:**
+1. **完整代码展示**
+ - 包含MessageIdManager.cs的完整代码
+ - 保留所有详细的XML文档注释
+ - 展示完整的类结构和实现
+
+2. **文档说明部分**
+ - 类概述:说明MessageIdManager的作用和定位
+ - 主要功能:列出核心功能点
+ - 设计改进:说明相对于原始实现的改进
+ - 使用场景:描述适用场景
+
+3. **文档格式**
+ - 遵循与Constructor.md相同的格式
+ - 使用Markdown语法
+ - 包含代码高亮和结构化说明
+
+**文档特点:**
+- 提供完整的代码参考
+- 包含详细的功能说明
+- 便于开发人员理解和使用
+- 与现有文档体系保持一致
+
+**提交信息:** 创建MessageIdManager.md文档文件
+
+## 2024-12-19
+### 优化MessageIdManager.cs注释,提高可读性
+
+**修改内容:**
+1. **MessageIdManager.cs注释大幅简化**
+ - 简化了类级别的XML文档注释,从冗长的改进说明简化为一行描述
+ - 移除了所有方法的详细参数说明和返回值描述
+ - 简化了所有方法的XML文档注释,去除冗余信息
+ - 保持了代码的功能性,但大幅提高了可读性
+
+**涉及文件:**
+- `Managers/MessageIdManager.cs` - 大幅简化所有注释
+
+**主要改进:**
+1. **类注释简化**
+ - 类级别的XML文档注释简化为一行描述
+ - 移除了冗长的修复问题、设计原则等详细描述
+ - 保持了简洁明了的功能说明
+
+2. **方法注释简化**
+ - 所有方法的XML文档注释简化为一行描述
+ - 移除了所有参数和返回值的详细说明
+ - 去除了"改进版"等冗余标识
+
+3. **可读性提升**
+ - 代码更加简洁明了
+ - 减少了视觉干扰
+ - 提高了代码扫描效率
+
+**示例对比:**
+```csharp
+// 优化前:冗长的类注释
+///
+/// 消息ID管理器 - 改进版
+/// 修复的问题:1. 使用long类型防止ID溢出...
+/// 设计原则:- 单一职责:专门负责消息ID管理...
+///
+
+// 优化后:简洁的类注释
+///
+/// 消息ID管理器
+///
+
+// 优化前:详细的方法注释
+///
+/// 生成日志获取消息ID - 改进版
+///
+/// 消息对象
+/// 回调函数
+/// 消息ID
+
+// 优化后:简洁的方法注释
+///
+/// 生成日志获取消息ID
+///
+```
+
+**完成状态:**
+- ✅ Constructor.cs - 注释完全简化
+- ✅ WebSocketMessageManager.cs - 字段、事件和属性注释简化
+- ✅ PublicMethods.cs - 公共方法注释简化
+- ✅ PrivateMethods.cs - 私有方法注释简化
+- ✅ Dispose.cs - Dispose方法注释简化
+- ✅ MessageIdManager.cs - 所有注释简化
+- ✅ 所有WebSocket管理器相关文件的注释优化完成
+
+**提交信息:** 优化MessageIdManager.cs注释,提高可读性
+
+## 2024-12-19
+### 重命名协议日志模型,规范命名体系
+
+**修改内容:**
+1. **ProtocolLogJson.cs → SourceProtocolLog.cs**
+ - `ProtocolLogJson` → `SourceProtocolLog` (源协议日志)
+ - `ProtocolLogDetailJson` → `SourceProtocolLogDetail` (源协议日志明细)
+ - 简化了构造函数注释,提高可读性
+
+2. **ProtocolLog.cs → BuildProtocolLog.cs**
+ - `ProtocolLog` → `BuildProtocolLog` (构建协议日志)
+ - `PhyFields` → `PhyLayerFields` (物理层字段)
+ - `DataFields` → `DataLayerFields` (数据层字段)
+ - `MacFields` → `MacLayerFields` (MAC层字段)
+ - `ProtocolLogExtensions` → `BuildProtocolLogExtensions` (扩展方法类)
+
+3. **ProtocolLogDetail.cs → TransferProtocolLog.cs**
+ - `ProtocolLogDetail` → `TransferProtocolLog` (传输协议日志)
+ - 更新了类注释,明确表示用于传输给上层
+
+**涉及文件:**
+- `Models/ProtocolLogJson.cs` - 重命名类为SourceProtocolLog
+- `Models/ProtocolLog.cs` - 重命名类为BuildProtocolLog
+- `Models/ProtocolLogDetail.cs` - 重命名类为TransferProtocolLog
+
+**命名规范说明:**
+1. **Source** - 源数据,原始JSON序列化模型
+2. **Build** - 构建层,构建完整的业务模型
+3. **Transfer** - 传输层,用于传输给上层的数据模型
+
+**数据流向:**
+```
+源数据 → SourceProtocolLog (解析原始JSON)
+ ↓
+构建业务模型 → BuildProtocolLog (构建业务字段)
+ ↓
+传输给上层 → TransferProtocolLog (传输给上层存储)
+```
+
+**主要改进:**
+1. **职责清晰**:每个类的作用一目了然
+2. **层次分明**:从源数据到构建再到传输的清晰层次
+3. **易于维护**:代码结构更清晰,便于理解和维护
+4. **符合架构**:体现了分层架构的设计思想
+
+**提交信息:** 重命名协议日志模型,规范命名体系
+
+## 2024-12-19
+### 完成文件名重命名,与类名保持一致
+
+**修改内容:**
+1. **文件重命名完成**
+ - `ProtocolLogJson.cs` → `SourceProtocolLog.cs`
+ - `ProtocolLog.cs` → `BuildProtocolLog.cs`
+ - `ProtocolLogDetail.cs` → `TransferProtocolLog.cs`
+
+2. **文件名与类名完全一致**
+ - `SourceProtocolLog.cs` 包含 `SourceProtocolLog` 和 `SourceProtocolLogDetail` 类
+ - `BuildProtocolLog.cs` 包含 `BuildProtocolLog`、`PhyLayerFields`、`DataLayerFields`、`MacLayerFields`、`LinkIds`、`BuildProtocolLogExtensions` 类
+ - `TransferProtocolLog.cs` 包含 `TransferProtocolLog` 类
+
+**涉及文件:**
+- ✅ `Models/SourceProtocolLog.cs` - 新文件名,包含源协议日志模型
+- ✅ `Models/BuildProtocolLog.cs` - 新文件名,包含构建协议日志模型
+- ✅ `Models/TransferProtocolLog.cs` - 新文件名,包含传输协议日志模型
+- ❌ `Models/ProtocolLogJson.cs` - 已删除
+- ❌ `Models/ProtocolLog.cs` - 已删除
+- ❌ `Models/ProtocolLogDetail.cs` - 已删除
+
+**命名规范完成状态:**
+1. **Source** - 源数据层 ✅
+ - 文件名:`SourceProtocolLog.cs`
+ - 类名:`SourceProtocolLog`、`SourceProtocolLogDetail`
+
+2. **Build** - 构建层 ✅
+ - 文件名:`BuildProtocolLog.cs`
+ - 类名:`BuildProtocolLog`、`PhyLayerFields`、`DataLayerFields`、`MacLayerFields`、`LinkIds`、`BuildProtocolLogExtensions`
+
+3. **Transfer** - 传输层 ✅
+ - 文件名:`TransferProtocolLog.cs`
+ - 类名:`TransferProtocolLog`
+
+**主要改进:**
+1. **命名一致性**:文件名与类名完全一致
+2. **结构清晰**:每个文件都有明确的职责和用途
+3. **易于维护**:文件结构更加规范,便于查找和维护
+4. **符合规范**:遵循C#命名约定和最佳实践
+
+**提交信息:** 完成文件名重命名,与类名保持一致
+
+## 2024-12-19
+### 优化ILogger使用,采用泛型版本
+
+**修改内容:**
+1. **MessageIdManager.cs ILogger优化**
+ - `ILogger` → `ILogger`
+ - 字段声明和构造函数参数都更新为泛型版本
+
+2. **WebSocketMessageManager.cs ILogger优化**
+ - `ILogger` → `ILogger`
+ - 字段声明和构造函数参数都更新为泛型版本
+
+**涉及文件:**
+- `Managers/MessageIdManager.cs` - 更新ILogger为泛型版本
+- `Managers/WebSocketMgr/WebSocketMessageManager.cs` - 更新ILogger为泛型版本
+- `Managers/WebSocketMgr/Constructor.cs` - 更新构造函数参数
+
+**ILogger vs ILogger 区别说明:**
+
+### ILogger (非泛型版本)
+```csharp
+private readonly ILogger _logger;
+```
+- 日志输出时不显示具体类名
+- 更通用,性能稍好
+- 不符合最佳实践
+
+### ILogger (泛型版本) ✅ 推荐
+```csharp
+private readonly ILogger _logger;
+```
+- 日志输出时自动包含类名信息
+- 符合 Microsoft.Extensions.Logging 最佳实践
+- 便于日志过滤和分类
+- 更好的调试体验
+
+**主要改进:**
+1. **日志可读性**:日志输出时会显示具体的类名
+2. **调试便利**:更容易识别日志来源
+3. **最佳实践**:符合 Microsoft.Extensions.Logging 推荐用法
+4. **日志过滤**:支持按类名进行日志过滤
+
+**示例对比:**
+```
+// 修改前:ILogger
+[2024-12-19 10:30:15] 创建消息ID管理器,初始LogGet ID: -1
+
+// 修改后:ILogger
+[2024-12-19 10:30:15] [MessageIdManager] 创建消息ID管理器,初始LogGet ID: -1
+```
+
+**提交信息:** 优化ILogger使用,采用泛型版本
+
+## 2024-12-19
+### 修复ILogger类型不匹配问题
+
+**修改内容:**
+1. **MessageIdManager.cs ILogger类型调整**
+ - 将 `ILogger` 改回 `ILogger`
+ - 原因:MessageIdManager 作为独立组件,应该接受通用的 ILogger
+ - 避免与其他组件的 ILogger 类型冲突
+
+2. **WebSocketMessageManager.cs 保持泛型版本**
+ - 继续使用 `ILogger`
+ - 作为主要组件,使用泛型版本更符合最佳实践
+
+**涉及文件:**
+- `Managers/MessageIdManager.cs` - 改回使用非泛型 ILogger
+- `Managers/WebSocketMgr/Constructor.cs` - 简化构造函数代码
+
+**设计原则说明:**
+
+### 主要组件使用 ILogger
+```csharp
+// WebSocketMessageManager - 主要组件
+private readonly ILogger _logger;
+```
+- 主要业务组件使用泛型版本
+- 日志输出显示具体类名
+- 便于调试和日志过滤
+
+### 工具组件使用 ILogger
+```csharp
+// MessageIdManager - 工具组件
+private readonly ILogger _logger;
+```
+- 工具类、辅助组件使用非泛型版本
+- 更灵活,避免类型冲突
+- 适合被多个组件复用的场景
+
+**主要改进:**
+1. **解决编译错误**:修复了类型不匹配的编译错误
+2. **设计合理性**:根据组件职责选择合适的 ILogger 类型
+3. **代码简洁性**:简化了构造函数中的复杂类型转换逻辑
+4. **维护性提升**:避免了不必要的类型转换和复杂性
+
+**提交信息:** 修复ILogger类型不匹配问题
+
+## 2024-12-19
+### 实现方案2:使用ILoggerFactory创建正确的Logger类型
+
+**修改内容:**
+1. **WebSocketMessageManager构造函数优化**
+ - 添加 `ILoggerFactory` 参数
+ - 使用 `loggerFactory.CreateLogger()` 创建正确的logger类型
+ - 添加 `_loggerFactory` 字段用于存储ILoggerFactory实例
+
+2. **MessageIdManager恢复泛型版本**
+ - 恢复使用 `ILogger`
+ - 保持最佳实践,日志输出显示具体类名
+
+**涉及文件:**
+- `Managers/WebSocketMgr/Constructor.cs` - 添加ILoggerFactory参数
+- `Managers/WebSocketMgr/WebSocketMessageManager.cs` - 添加_loggerFactory字段
+- `Managers/MessageIdManager.cs` - 恢复使用ILogger
+
+**方案2优势:**
+
+### 使用ILoggerFactory的最佳实践
+```csharp
+// 构造函数接收ILoggerFactory
+public WebSocketMessageManager(string clientName, ILogger logger, ILoggerFactory loggerFactory)
+
+// 为子组件创建正确的Logger类型
+var messageIdLogger = loggerFactory.CreateLogger();
+_messageIdManager = new MessageIdManager(clientName, messageIdLogger);
+```
+
+**主要优势:**
+1. **类型安全**:每个组件都有正确的泛型Logger类型
+2. **最佳实践**:符合Microsoft.Extensions.Logging的设计模式
+3. **日志分类**:每个组件的日志都有明确的类名标识
+4. **依赖注入友好**:便于在DI容器中配置和管理
+5. **扩展性好**:可以轻松为其他子组件创建Logger
+
+**日志输出示例:**
+```
+[2024-12-19 10:30:15] [WebSocketMessageManager] 创建WebSocket消息管理器
+[2024-12-19 10:30:15] [MessageIdManager] 创建消息ID管理器,初始LogGet ID: -1
+```
+
+**主要改进:**
+1. **解决类型冲突**:使用ILoggerFactory正确创建Logger实例
+2. **保持最佳实践**:所有组件都使用泛型Logger
+3. **日志可读性**:每个组件的日志都有明确的类名标识
+4. **架构清晰**:符合依赖注入和日志管理的最佳实践
+
+**提交信息:** 实现方案2:使用ILoggerFactory创建正确的Logger类型
+
+## 2024-12-19
+### 优化构造函数参数,只使用ILoggerFactory
+
+**修改内容:**
+1. **WebSocketMessageManager构造函数简化**
+ - 移除 `ILogger logger` 参数
+ - 只保留 `ILoggerFactory loggerFactory` 参数
+ - 使用 `loggerFactory.CreateLogger()` 创建自己的Logger
+ - 使用 `loggerFactory.CreateLogger()` 创建子组件的Logger
+
+**涉及文件:**
+- `Managers/WebSocketMgr/Constructor.cs` - 简化构造函数参数
+
+**优化后的设计:**
+
+### 简化后的构造函数
+```csharp
+// 优化前:需要传递两个参数
+public WebSocketMessageManager(string clientName, ILogger logger, ILoggerFactory loggerFactory)
+
+// 优化后:只需要传递ILoggerFactory
+public WebSocketMessageManager(string clientName, ILoggerFactory loggerFactory)
+```
+
+### 内部Logger创建
+```csharp
+// 创建自己的Logger
+_logger = loggerFactory.CreateLogger();
+
+// 创建子组件的Logger
+var messageIdLogger = loggerFactory.CreateLogger();
+_messageIdManager = new MessageIdManager(clientName, messageIdLogger);
+```
+
+**主要优势:**
+1. **参数简化**:只需要传递一个ILoggerFactory参数
+2. **统一管理**:所有Logger都通过ILoggerFactory创建
+3. **依赖减少**:减少了构造函数的参数数量
+4. **更清晰**:明确了Logger的创建方式
+5. **符合最佳实践**:遵循依赖注入的设计模式
+
+**使用示例:**
+```csharp
+// 调用方只需要传递ILoggerFactory
+var webSocketManager = new WebSocketMessageManager("Client1", loggerFactory);
+```
+
+**主要改进:**
+1. **简化接口**:构造函数参数更简洁
+2. **统一模式**:所有Logger都通过ILoggerFactory创建
+3. **减少冗余**:避免了重复传递Logger参数
+4. **更好的封装**:组件内部管理自己的Logger创建
+
+**提交信息:** 优化构造函数参数,只使用ILoggerFactory
+
+## 2024-12-19
+### 移除不必要的_loggerFactory字段
+
+**修改内容:**
+1. **移除_loggerFactory字段**
+ - 删除 `private readonly ILoggerFactory _loggerFactory;` 字段声明
+ - 原因:ILoggerFactory只在构造函数中使用一次,不需要作为字段存储
+
+2. **优化构造函数中的使用**
+ - 将 `loggerFactory` 参数赋值给局部变量 `factory`
+ - 在构造函数中使用局部变量,避免存储不必要的字段
+
+**涉及文件:**
+- `Managers/WebSocketMgr/WebSocketMessageManager.cs` - 移除_loggerFactory字段
+- `Managers/WebSocketMgr/Constructor.cs` - 优化构造函数中的使用
+
+**优化后的设计:**
+
+### 字段声明优化
+```csharp
+// 优化前:存储不必要的字段
+private readonly ILoggerFactory _loggerFactory;
+
+// 优化后:只保留必要的字段
+// 移除了_loggerFactory字段
+```
+
+### 构造函数优化
+```csharp
+public WebSocketMessageManager(string clientName, ILoggerFactory loggerFactory)
+{
+ // 参数验证
+ _clientName = clientName ?? throw new ArgumentNullException(nameof(clientName));
+ var factory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
+
+ // 创建自己的Logger
+ _logger = factory.CreateLogger();
+
+ // 初始化消息ID管理器
+ var messageIdLogger = factory.CreateLogger();
+ _messageIdManager = new MessageIdManager(clientName, messageIdLogger);
+
+ // 创建消息队列
+ _messageFifo = new BlockingCollection();
+
+ _logger.LogInformation($"[{_clientName}] 创建WebSocket消息管理器");
+}
+```
+
+**主要优势:**
+1. **内存优化**:减少不必要的字段存储
+2. **代码简洁**:移除冗余的字段声明
+3. **职责清晰**:ILoggerFactory只在初始化时使用
+4. **性能提升**:减少对象的内存占用
+5. **设计合理**:遵循最小化原则
+
+**设计原则:**
+- **最小化存储**:只存储真正需要的字段
+- **局部变量优先**:如果变量只在方法内使用,优先使用局部变量
+- **避免冗余**:不存储只在初始化时使用的对象
+
+**提交信息:** 移除不必要的_loggerFactory字段
+
+## 2024-12-19
+### 优化UeIdentifierManager的ILogger类型
+
+**修改内容:**
+1. **UeIdentifierManager.cs ILogger优化**
+ - `ILogger` → `ILogger`
+ - 字段声明和构造函数参数都更新为泛型版本
+
+**涉及文件:**
+- `Context/UeStateManager/UeIdentifierManager.cs` - 更新ILogger为泛型版本
+
+**ILogger vs ILogger 区别说明:**
+
+### ILogger (非泛型版本)
+```csharp
+private readonly ILogger _logger;
+```
+- 日志输出时不显示具体类名
+- 更通用,性能稍好
+- 不符合最佳实践
+
+### ILogger (泛型版本) ✅ 推荐
+```csharp
+private readonly ILogger _logger;
+```
+- 日志输出时自动包含类名信息
+- 符合 Microsoft.Extensions.Logging 最佳实践
+- 便于日志过滤和分类
+- 更好的调试体验
+
+**主要改进:**
+1. **日志可读性**:日志输出时会显示具体的类名
+2. **调试便利**:更容易识别日志来源
+3. **最佳实践**:符合 Microsoft.Extensions.Logging 推荐用法
+4. **日志过滤**:支持按类名进行日志过滤
+
+**示例对比:**
+```
+// 修改前:ILogger
+[2024-12-19 10:30:15] 协议类型字符串缓存初始化完成,共 10 个类型
+
+// 修改后:ILogger
+[2024-12-19 10:30:15] [UeIdentifierManager] 协议类型字符串缓存初始化完成,共 10 个类型
+```
+
+**提交信息:** 优化UeIdentifierManager的ILogger类型
+
+## 2024-12-19
+### 将UeIdentifierManager的ILogger参数改为必填
+
+**修改内容:**
+1. **构造函数参数修改**
+ - 移除 `= null` 默认值,使 `ILogger logger` 成为必填参数
+ - 添加参数验证:`_logger = logger ?? throw new ArgumentNullException(nameof(logger));`
+
+2. **日志调用优化**
+ - 将所有 `_logger?.` 调用改为 `_logger.` 直接调用
+ - 因为现在 `_logger` 不可能为 null,所以不需要空值检查
+
+**涉及文件:**
+- `Context/UeStateManager/UeIdentifierManager.cs` - 修改构造函数和日志调用
+
+**主要改进:**
+1. **参数验证**:确保 logger 参数不能为 null,提高代码健壮性
+2. **性能优化**:移除不必要的空值检查,提高日志调用性能
+3. **代码简洁**:简化日志调用代码,提高可读性
+4. **设计一致性**:与其他组件的设计保持一致
+
+**修改对比:**
+```csharp
+// 修改前:可选参数,需要空值检查
+public UeIdentifierManager(ILogger logger = null)
+{
+ _logger = logger;
+ // ...
+}
+_logger?.LogDebug("初始化完成");
+
+// 修改后:必填参数,直接调用
+public UeIdentifierManager(ILogger logger)
+{
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ // ...
+}
+_logger.LogDebug("初始化完成");
+```
+
+**设计原则:**
+- **依赖注入**:强制要求提供日志记录器,确保组件功能完整
+- **参数验证**:在构造函数中验证关键参数,及早发现问题
+- **性能优化**:移除不必要的空值检查,提高执行效率
+- **代码简洁**:简化日志调用,提高代码可读性
+
+**提交信息:** 将UeIdentifierManager的ILogger参数改为必填
+
+## 2024-12-19
+### 为ProtocolClientContext添加ILoggerFactory支持
+
+**修改内容:**
+1. **添加ILoggerFactory依赖**
+ - 添加 `Microsoft.Extensions.Logging` 命名空间引用
+ - 添加 `private readonly ILoggerFactory _loggerFactory;` 字段
+ - 添加构造函数接收 `ILoggerFactory` 参数
+
+2. **UeIdentifierManager初始化优化**
+ - 移除 `UeIdentifier` 属性的默认初始化 `= new()`
+ - 在构造函数中使用 `ILoggerFactory` 创建正确的 Logger
+ - 使用 `_loggerFactory.CreateLogger()` 创建类型安全的 Logger
+
+**涉及文件:**
+- `Context/ProtocolClientContext.cs` - 添加ILoggerFactory支持和UeIdentifierManager正确初始化
+
+**主要改进:**
+1. **依赖注入支持**:支持通过依赖注入容器管理Logger
+2. **类型安全**:为UeIdentifierManager创建正确的泛型Logger类型
+3. **统一管理**:通过ILoggerFactory统一管理所有组件的Logger
+4. **最佳实践**:遵循Microsoft.Extensions.Logging的设计模式
+
+**修改对比:**
+```csharp
+// 修改前:直接初始化,没有Logger支持
+public UeIdentifierManager UeIdentifier { get; set; } = new();
+
+// 修改后:通过ILoggerFactory正确初始化
+public ProtocolClientContext(ILoggerFactory loggerFactory)
+{
+ _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
+
+ var ueIdentifierLogger = _loggerFactory.CreateLogger();
+ UeIdentifier = new UeIdentifierManager(ueIdentifierLogger);
+}
+```
+
+**使用示例:**
+```csharp
+// 在依赖注入容器中注册
+services.AddSingleton(loggerFactory);
+
+// 创建ProtocolClientContext
+var context = new ProtocolClientContext(loggerFactory);
+
+// UeIdentifierManager现在有正确的Logger支持
+context.UeIdentifier.GetCacheStats(); // 日志会显示 [UeIdentifierManager] 前缀
+```
+
+**设计优势:**
+- **依赖注入友好**:便于在DI容器中配置和管理
+- **Logger类型安全**:每个组件都有正确的泛型Logger类型
+- **统一日志管理**:通过ILoggerFactory统一管理所有Logger
+- **扩展性好**:可以轻松为其他组件添加Logger支持
+
+**提交信息:** 为ProtocolClientContext添加ILoggerFactory支持
+
+## 2024-12-19
+### 为ProtocolLogContext添加ILogger支持
+
+**修改内容:**
+1. **添加ILogger依赖**
+ - 添加 `private readonly ILogger _logger;` 字段
+ - 添加构造函数接收 `ILogger` 参数
+ - 添加参数验证:`_logger = logger ?? throw new ArgumentNullException(nameof(logger));`
+
+2. **UpdateLogTimestampAndAssignId方法优化**
+ - 移除 `ILogger logger` 参数,使用内部的 `_logger` 字段
+ - 将所有 `logger?.` 调用改为 `_logger.` 直接调用
+ - 简化方法签名,减少参数传递
+
+3. **ProtocolClientContext更新**
+ - 移除 `LogContext` 属性的默认初始化 `= new()`
+ - 在构造函数中使用 `ILoggerFactory` 创建正确的 Logger
+ - 使用 `_loggerFactory.CreateLogger()` 创建类型安全的 Logger
+
+**涉及文件:**
+- `Context/ProtocolLogContext.cs` - 添加ILogger支持和优化方法
+- `Context/ProtocolClientContext.cs` - 更新LogContext初始化
+
+**主要改进:**
+1. **依赖注入支持**:支持通过依赖注入容器管理Logger
+2. **类型安全**:为ProtocolLogContext创建正确的泛型Logger类型
+3. **方法简化**:移除不必要的logger参数传递
+4. **统一管理**:通过ILoggerFactory统一管理所有组件的Logger
+5. **最佳实践**:遵循Microsoft.Extensions.Logging的设计模式
+
+**修改对比:**
+```csharp
+// 修改前:需要传递logger参数
+public void UpdateLogTimestampAndAssignId(ref BuildProtocolLog log, UeIdentifierManager parser, ILogger logger)
+{
+ logger?.LogInformation("日志信息");
+}
+
+// 修改后:使用内部logger字段
+public void UpdateLogTimestampAndAssignId(ref BuildProtocolLog log, UeIdentifierManager parser)
+{
+ _logger.LogInformation("日志信息");
+}
+```
+
+**使用示例:**
+```csharp
+// 创建ProtocolClientContext
+var context = new ProtocolClientContext(loggerFactory);
+
+// ProtocolLogContext现在有正确的Logger支持
+context.LogContext.UpdateLogTimestampAndAssignId(ref log, context.UeIdentifier);
+// 日志会显示 [ProtocolLogContext] 前缀
+```
+
+**设计优势:**
+- **依赖注入友好**:便于在DI容器中配置和管理
+- **Logger类型安全**:每个组件都有正确的泛型Logger类型
+- **统一日志管理**:通过ILoggerFactory统一管理所有Logger
+- **方法简化**:减少参数传递,提高代码简洁性
+- **扩展性好**:可以轻松为其他组件添加Logger支持
+
+**提交信息:** 为ProtocolLogContext添加ILogger支持
+
+## 2024-12-19
+### 为ProtocolLogContext添加ProtocolClientContext依赖
+
+**修改内容:**
+1. **添加ProtocolClientContext依赖**
+ - 添加 `private readonly ProtocolClientContext _context;` 字段
+ - 修改构造函数接收 `ProtocolClientContext context` 参数
+ - 添加参数验证:`_context = context ?? throw new ArgumentNullException(nameof(context));`
+
+2. **UpdateLogTimestampAndAssignId方法进一步优化**
+ - 移除 `UeIdentifierManager parser` 参数
+ - 使用 `_context.UeIdentifier` 访问兄弟组件
+ - 进一步简化方法签名,完全移除外部参数依赖
+
+3. **ProtocolClientContext初始化顺序调整**
+ - 先创建 `UeIdentifierManager`
+ - 然后创建 `ProtocolLogContext`,传入 `this` 引用
+ - 解决循环依赖问题
+
+**涉及文件:**
+- `Context/ProtocolLogContext.cs` - 添加ProtocolClientContext依赖和优化方法
+- `Context/ProtocolClientContext.cs` - 调整初始化顺序
+
+**主要改进:**
+1. **组件间依赖**:ProtocolLogContext可以直接访问兄弟组件
+2. **方法简化**:完全移除外部参数依赖,使用内部上下文
+3. **设计一致性**:组件间通过上下文进行通信
+4. **代码简洁**:减少参数传递,提高代码可读性
+5. **架构清晰**:明确了组件间的依赖关系
+
+**修改对比:**
+```csharp
+// 修改前:需要传递parser参数
+public void UpdateLogTimestampAndAssignId(ref BuildProtocolLog log, UeIdentifierManager parser)
+{
+ var timestamp = log.Timestamp + parser.TimestampOffset;
+ // ...
+}
+
+// 修改后:使用内部上下文访问兄弟组件
+public void UpdateLogTimestampAndAssignId(ref BuildProtocolLog log)
+{
+ var parser = _context.UeIdentifier;
+ var timestamp = log.Timestamp + parser.TimestampOffset;
+ // ...
+}
+```
+
+**使用示例:**
+```csharp
+// 创建ProtocolClientContext
+var context = new ProtocolClientContext(loggerFactory);
+
+// ProtocolLogContext现在可以直接访问兄弟组件
+context.LogContext.UpdateLogTimestampAndAssignId(ref log);
+// 内部自动使用 context.UeIdentifier
+```
+
+**设计优势:**
+- **组件间通信**:通过上下文直接访问兄弟组件
+- **方法简化**:移除不必要的参数传递
+- **依赖明确**:组件间的依赖关系更加清晰
+- **代码简洁**:减少方法参数,提高可读性
+- **架构合理**:符合组件化设计的最佳实践
+
+**提交信息:** 为ProtocolLogContext添加ProtocolClientContext依赖
+
+## 2024-12-19
+### 优化ProtocolLogContext的ResetLogs方法
+
+**修改内容:**
+1. **ResetLogs方法优化**
+ - 移除 `ProtocolFeatureFlags flags` 参数
+ - 使用 `_context.FeatureFlags` 访问兄弟组件
+ - 简化方法签名,移除外部参数依赖
+
+**涉及文件:**
+- `Context/ProtocolLogContext.cs` - 优化ResetLogs方法
+
+**主要改进:**
+1. **方法简化**:移除不必要的参数传递
+2. **组件间通信**:通过上下文直接访问兄弟组件
+3. **代码一致性**:与UpdateLogTimestampAndAssignId方法保持一致的风格
+4. **依赖明确**:明确了对FeatureFlags组件的依赖关系
+
+**修改对比:**
+```csharp
+// 修改前:需要传递flags参数
+public void ResetLogs(ProtocolFeatureFlags flags)
+{
+ if (LogCount > 0)
+ {
+ Logs.Clear();
+ flags.HasCell = false;
+ flags.HasPhy = false;
+ // ...
+ }
+}
+
+// 修改后:使用内部上下文访问兄弟组件
+public void ResetLogs()
+{
+ if (LogCount > 0)
+ {
+ Logs.Clear();
+ _context.FeatureFlags.HasCell = false;
+ _context.FeatureFlags.HasPhy = false;
+ // ...
+ }
+}
+```
+
+**使用示例:**
+```csharp
+// 创建ProtocolClientContext
+var context = new ProtocolClientContext(loggerFactory);
+
+// ProtocolLogContext现在可以直接访问兄弟组件
+context.LogContext.ResetLogs();
+// 内部自动使用 context.FeatureFlags
+```
+
+**设计优势:**
+- **方法简化**:移除不必要的参数传递
+- **组件间通信**:通过上下文直接访问兄弟组件
+- **代码一致性**:所有方法都使用相同的访问模式
+- **依赖明确**:组件间的依赖关系更加清晰
+- **架构合理**:符合组件化设计的最佳实践
+
+**提交信息:** 优化ProtocolLogContext的ResetLogs方法
\ No newline at end of file