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
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
}
}