You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

21 KiB

PublicMethods.cs (自动转换为Markdown)

// 以下内容为原始C#代码,含详细注释
// 文件原路径:Managers/WebSocketMgr/PublicMethods.cs

using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebSocket4Net;
using CoreAgent.ProtocolClient.Models;

namespace CoreAgent.ProtocolClient.Managers.WebSocketMgr
{
    public partial class WebSocketMessageManager
    {
        #region 公共方法

        /// <summary>
        /// 连接到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()
        /// - 异常处理:对应原始实现中的异常处理逻辑
        /// - 日志记录:对应原始实现中的日志记录
        /// 
        /// 重构改进:
        /// - 更明确的参数验证
        /// - 更详细的异常处理
        /// - 更清晰的错误信息
        /// - 保持了完全一致的连接逻辑
        /// </summary>
        /// <param name="url">WebSocket URL,对应LTEClientWebSocket._config.Address</param>
        /// <param name="ssl">是否使用SSL,对应LTEClientWebSocket._config.Ssl</param>
        public void Connect(string url, bool ssl = false)
        {
            ThrowIfDisposed();

            if (string.IsNullOrEmpty(url))
                throw new ArgumentException("URL不能为空", nameof(url));

            try
            {
                _logger.LogInformation($"[{_clientName}] 尝试连接: {url}");

                // 构建WebSocket URL - 对应原始实现中的URL构建逻辑
                var fullUrl = (ssl ? "wss://" : "ws://") + url;

                // 创建WebSocket实例 - 对应原始实现中的_webSocket创建
                _webSocket = new WebSocket(fullUrl);
                _webSocket.EnableAutoSendPing = false;

                // 绑定事件处理器 - 对应原始实现中的事件绑定
                _webSocket.Opened += OnSocketOpened!;
                _webSocket.Closed += OnSocketClosed!;
                _webSocket.MessageReceived += OnSocketMessageReceived!; // 对应OnSocketMessage0
                _webSocket.Error += OnSocketError!;

                // 打开连接 - 对应原始实现中的_webSocket.Open()
                _webSocket.Open();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"[{_clientName}] 连接异常: {ex.Message}");
                ConnectionError?.Invoke(this, $"无法连接到 {url}: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 断开WebSocket连接 - 对应LTEClientWebSocket.Stop()方法中的WebSocket相关逻辑
        /// 
        /// 功能说明:
        /// 1. 关闭WebSocket连接,对应原始Stop()方法的核心逻辑
        /// 2. 清理消息队列和定时器,对应原始的资源清理逻辑
        /// 3. 提供更完善的异常处理
        /// 
        /// 与原始实现的差异:
        /// - 方法名从Stop()改为Disconnect(),更明确表达功能
        /// - 移除了状态管理逻辑(SetState),专注连接管理
        /// - 移除了重连逻辑,专注连接断开
        /// 
        /// 详细对应关系:
        /// - 定时器停止:对应原始StopTimers()中的_messageDeferTimer处理
        /// - 队列清理:对应原始实现中的队列清理逻辑
        /// - WebSocket关闭:对应原始实现中的_webSocket.Close()
        /// - 资源清理:对应原始实现中的资源清理逻辑
        /// - 异常处理:对应原始实现中的异常处理
        /// - 日志记录:对应原始实现中的日志记录
        /// 
        /// 重构改进:
        /// - 更清晰的资源清理顺序
        /// - 更完善的异常处理
        /// - 更详细的日志记录
        /// - 保持了完全一致的清理逻辑
        /// </summary>
        public void Disconnect()
        {
            ThrowIfDisposed();

            try
            {
                _logger.LogInformation($"[{_clientName}] 断开连接");

                // 停止消息发送定时器 - 对应原始StopTimers()中的_messageDeferTimer处理
                StopMessageDeferTimer();

                // 清空消息队列 - 对应原始实现中的队列清理
                ClearMessageQueue();

                // 关闭WebSocket连接 - 对应原始实现中的_webSocket.Close()
                if (_webSocket != null)
                {
                    _webSocket.Close();
                    _webSocket = null;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"[{_clientName}] 断开连接异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 发送消息 - 对应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管理
        /// - 更严格的参数验证
        /// - 更详细的日志记录
        /// - 保持了完全一致的发送逻辑
        /// </summary>
        /// <param name="message">消息对象,对应原始方法中的message参数</param>
        /// <param name="callback">回调函数,对应原始方法中的callback参数</param>
        /// <param name="errorHandler">是否为错误处理器,对应原始方法中的errorHandler参数</param>
        /// <returns>消息ID,对应原始方法的返回值</returns>
        public long SendMessage(JObject message, Action<JObject>? callback = null, bool errorHandler = false)
        {
            ThrowIfDisposed();

            if (message == null)
                throw new ArgumentNullException(nameof(message));

            // 检查连接状态 - 对应原始实现中的连接状态检查
            if (!IsConnected)
            {
                _logger.LogWarning($"[{_clientName}] WebSocket未连接,无法发送消息");
                return -1L;
            }

            // 使用MessageIdManager生成ID - 替代原始的Interlocked.Increment(ref _messageId)
            var messageId = _messageIdManager.GenerateGeneralMessageId(message, callback, errorHandler);

            // 添加到消息队列 - 对应原始实现中的_messageFifo.Enqueue(message)
            _messageFifo.Add(message);

            // 启动消息发送定时器 - 对应原始实现中的定时器启动逻辑
            StartMessageDeferTimer();

            _logger.LogDebug($"[{_clientName}] 消息已加入队列: message_id={messageId}");
            return messageId;
        }

        /// <summary>
        /// 发送日志获取消息 - 对应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
        /// - 保持了完全一致的发送逻辑
        /// </summary>
        /// <param name="message">消息对象,对应原始LogGet()方法中构建的message</param>
        /// <param name="callback">回调函数,对应原始LogGet()方法中的LogGetParse回调</param>
        /// <returns>消息ID,对应原始方法的返回值</returns>
        public long SendLogGetMessage(JObject message, Action<JObject> callback)
        {
            ThrowIfDisposed();

            if (message == null)
                throw new ArgumentNullException(nameof(message));

            if (callback == null)
                throw new ArgumentNullException(nameof(callback));

            // 检查连接状态 - 对应原始实现中的连接状态检查
            if (!IsConnected)
            {
                _logger.LogWarning($"[{_clientName}] WebSocket未连接,无法发送日志获取消息");
                return -1L;
            }

            // 使用MessageIdManager生成LogGet ID - 替代原始的_logGetId管理
            var messageId = _messageIdManager.GenerateLogGetMessageId(message, callback);

            // 委托给SendMessage方法,避免代码重复 - 对应原始实现中的SendMessage调用
            // 注意:这里不需要再次调用SendMessage,因为GenerateLogGetMessageId已经处理了消息ID和回调注册
            // 只需要将消息加入队列并启动定时器
            _messageFifo.Add(message);
            StartMessageDeferTimer();

            _logger.LogDebug($"[{_clientName}] 日志获取消息已加入队列: message_id={messageId}");
            return messageId;
        }

        /// <summary>
        /// 处理接收到的消息 - 对应LTEClientWebSocket.OnSocketMessage()方法中的消息处理逻辑
        /// 
        /// 功能说明:
        /// 1. 处理接收到的WebSocket消息,对应原始OnSocketMessage()方法的核心逻辑
        /// 2. 使用MessageIdManager处理消息响应,替代原始的消息处理器查找逻辑
        /// 3. 触发MessageReceived事件,对应原始的事件触发
        /// 4. 提供完善的错误处理
        /// 
        /// 与原始实现的差异:
        /// - 使用MessageIdManager处理消息响应,提供更好的管理
        /// - 移除了消息缓存逻辑(_receivedMessages),专注处理
        /// - 移除了业务逻辑处理(log_get、stats等),专注消息路由
        /// - 保持了完全一致的事件触发逻辑
        /// 
        /// 详细对应关系:
        /// - 参数message:对应原始方法中的msg参数
        /// - 参数errorHandler:对应原始方法中的错误处理逻辑
        /// - 消息处理器查找:对应原始的消息处理器查找逻辑
        /// - 事件触发:对应原始的事件触发逻辑
        /// - 错误处理:对应原始的错误处理逻辑
        /// - 返回值:新增返回值提供处理状态反馈
        /// - 日志记录:对应原始实现中的日志记录
        /// 
        /// 重构改进:
        /// - 更统一的消息响应处理
        /// - 更清晰的错误处理
        /// - 更详细的日志记录
        /// - 保持了完全一致的处理逻辑
        /// </summary>
        /// <param name="message">接收到的消息,对应原始方法中的msg参数</param>
        /// <param name="errorHandler">错误处理回调,对应原始方法中的错误处理逻辑</param>
        /// <returns>是否成功处理,新增返回值提供处理状态反馈</returns>
        public bool HandleReceivedMessage(JObject message, Action<string>? errorHandler = null)
        {
            ThrowIfDisposed();

            if (message == null)
                return false;

            try
            {
                // 使用MessageIdManager处理消息响应 - 替代原始的消息处理器查找逻辑
                var handled = _messageIdManager.HandleMessageResponse(message, errorHandler);

                if (handled)
                {
                    _logger.LogDebug($"[{_clientName}] 消息已处理: message_id={message["message_id"]}");
                    return true;
                }

                // 处理特定消息类型 - 对应原始实现中的特定消息类型处理
                // 注意:这里不处理log_get和stats等业务逻辑,因为重构版本专注于消息传输
                var name = message["message"]?.ToString();
                if (!string.IsNullOrEmpty(name))
                {
                    _logger.LogDebug($"[{_clientName}] 未处理的特定消息类型: {name}");
                }

                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"[{_clientName}] 处理消息异常: {ex.Message}");
                errorHandler?.Invoke($"消息处理错误: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 设置消息处理器 - 对应LTEClientWebSocket.SetMessageHandler()方法
        /// 
        /// 功能说明:
        /// 1. 设置按名称的消息处理器,对应原始SetMessageHandler()方法的核心逻辑
        /// 2. 委托给MessageIdManager处理,提供统一的消息处理器管理
        /// 3. 支持多个消息名称的处理器设置
        /// 
        /// 详细对应关系:
        /// - 参数names:对应原始方法中的names参数,消息名称数组
        /// - 参数handler:对应原始方法中的handler参数,消息处理器
        /// - 处理器注册:对应原始的_messageHandlersByName注册逻辑
        /// - 日志记录:对应原始实现中的日志记录
        /// 
        /// 重构改进:
        /// - 委托给MessageIdManager,提供统一管理
        /// - 保持了完全一致的接口和功能
        /// - 更好的错误处理和参数验证
        /// </summary>
        /// <param name="names">消息名称数组,对应原始方法中的names参数</param>
        /// <param name="handler">消息处理器,对应原始方法中的handler参数</param>
        public void SetMessageHandler(string[] names, MessageHandler handler)
        {
            ThrowIfDisposed();
            _messageIdManager.SetMessageHandler(names, handler);
        }

        /// <summary>
        /// 取消设置消息处理器 - 对应LTEClientWebSocket.UnsetMessageHandler()方法
        /// 
        /// 功能说明:
        /// 1. 取消按名称的消息处理器,对应原始UnsetMessageHandler()方法的核心逻辑
        /// 2. 委托给MessageIdManager处理,提供统一的消息处理器管理
        /// 3. 支持多个消息名称的处理器取消
        /// 
        /// 详细对应关系:
        /// - 参数names:对应原始方法中的names参数,消息名称数组
        /// - 处理器移除:对应原始的_messageHandlersByName移除逻辑
        /// - 日志记录:对应原始实现中的日志记录
        /// 
        /// 重构改进:
        /// - 委托给MessageIdManager,提供统一管理
        /// - 保持了完全一致的接口和功能
        /// - 更好的错误处理和参数验证
        /// </summary>
        /// <param name="names">消息名称数组,对应原始方法中的names参数</param>
        public void UnsetMessageHandler(string[] names)
        {
            ThrowIfDisposed();
            _messageIdManager.UnsetMessageHandler(names);
        }

        /// <summary>
        /// 检查是否为当前日志获取消息 - 对应LTEClientWebSocket中的_logGetId检查逻辑
        /// 
        /// 功能说明:
        /// 1. 检查指定的消息ID是否为当前的日志获取消息ID
        /// 2. 委托给MessageIdManager处理,提供统一的LogGet ID管理
        /// 3. 用于日志获取流程的状态检查
        /// 
        /// 详细对应关系:
        /// - 参数messageId:对应原始实现中的消息ID检查
        /// - 返回值:true表示是当前LogGet消息,false表示不是,对应原始逻辑
        /// - 检查逻辑:对应原始的_logGetId比较逻辑
        /// 
        /// 重构改进:
        /// - 委托给MessageIdManager,提供统一管理
        /// - 保持了完全一致的检查逻辑
        /// - 更好的线程安全性
        /// </summary>
        /// <param name="messageId">要检查的消息ID</param>
        /// <returns>是否为当前日志获取消息</returns>
        public bool IsCurrentLogGetMessage(long messageId)
        {
            ThrowIfDisposed();
            return _messageIdManager.IsCurrentLogGetMessage(messageId);
        }

        /// <summary>
        /// 重置日志获取ID - 对应LTEClientWebSocket中的_logGetId重置逻辑
        /// 
        /// 功能说明:
        /// 1. 重置日志获取消息ID,对应原始实现中的_logGetId重置逻辑
        /// 2. 委托给MessageIdManager处理,提供统一的LogGet ID管理
        /// 3. 用于日志获取流程的重置操作
        /// 
        /// 详细对应关系:
        /// - 重置逻辑:对应原始的_logGetId = -1操作
        /// - 日志记录:对应原始实现中的日志记录
        /// - 事件触发:对应原始实现中的状态变化通知
        /// 
        /// 重构改进:
        /// - 委托给MessageIdManager,提供统一管理
        /// - 保持了完全一致的重置逻辑
        /// - 更好的事件通知机制
        /// </summary>
        public void ResetLogGetId()
        {
            ThrowIfDisposed();
            _messageIdManager.ResetLogGetId();
        }

        /// <summary>
        /// 清理过期的消息处理器 - 对应LTEClientWebSocket中的处理器清理逻辑
        /// 
        /// 功能说明:
        /// 1. 清理过期的消息处理器,防止内存泄漏
        /// 2. 委托给MessageIdManager处理,提供统一的处理器管理
        /// 3. 支持可配置的过期时间
        /// 
        /// 详细对应关系:
        /// - 参数maxAge:对应原始实现中的过期时间配置
        /// - 清理逻辑:对应原始的处理器清理逻辑
        /// - 日志记录:对应原始实现中的日志记录
        /// 
        /// 重构改进:
        /// - 委托给MessageIdManager,提供统一管理
        /// - 保持了完全一致的清理逻辑
        /// - 更好的内存管理
        /// </summary>
        /// <param name="maxAge">最大存活时间(毫秒),默认30000毫秒</param>
        public void CleanupExpiredHandlers(int maxAge = 30000)
        {
            ThrowIfDisposed();
            _messageIdManager.CleanupExpiredHandlers(maxAge);
        }

        #endregion
    }
}