using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LTEMvcApp.Models;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using System.Text.Json;
namespace LTEMvcApp.Services
{
///
/// WebSocket管理器服务 - 管理多个LTE客户端连接
///
public class WebSocketManagerService
{
#region 私有字段
private readonly ConcurrentDictionary _clients;
private readonly ILogger _logger;
private readonly IServiceProvider _serviceProvider;
private List _testClientConfigs; // 只保留多个测试配置
private const int LogCacheSize = 10000; // 服务器最多缓存10000条最新日志
private readonly ConcurrentQueue _logCache = new ConcurrentQueue();
private readonly string _configsFilePath = "test_client_configs.json"; // 只保留多个配置文件路径
private readonly StatisticsService _statisticsService; // 添加统计服务
private readonly string _statisticsConfigFilePath = "statistics_config.json"; // 统计配置文件路径
private GlobalStatisticsConfig _globalStatisticsConfig; // 全局统计配置
#endregion
#region 事件
///
/// 客户端连接事件
///
public event EventHandler? ClientConnected;
///
/// 客户端断开事件
///
public event EventHandler? ClientDisconnected;
///
/// 日志接收事件
///
public event EventHandler<(string clientName, List logs)>? LogsReceived;
///
/// 状态变化事件
///
public event EventHandler<(string clientName, ClientState state)>? StateChanged;
///
/// 统计数据更新事件
///
public event EventHandler? StatisticsUpdated;
#endregion
#region 构造函数
///
/// 构造函数
///
public WebSocketManagerService(ILogger logger, IServiceProvider serviceProvider)
{
_clients = new ConcurrentDictionary();
_logger = logger;
_serviceProvider = serviceProvider;
_testClientConfigs = new List(); // 初始化测试配置列表
_statisticsService = serviceProvider.GetRequiredService(); // 通过依赖注入获取统计服务
_globalStatisticsConfig = new GlobalStatisticsConfig(); // 初始化全局统计配置
LoadTestClientConfigs(); // 加载多个测试配置
LoadStatisticsConfig(); // 加载统计配置
// 订阅统计服务事件
_statisticsService.StatsUpdated += (sender, stats) => StatisticsUpdated?.Invoke(this, stats);
_logger.LogInformation("WebSocketManagerService 初始化");
}
///
/// 加载多个测试客户端配置
///
private void LoadTestClientConfigs()
{
try
{
if (File.Exists(_configsFilePath))
{
var json = File.ReadAllText(_configsFilePath);
_testClientConfigs = JsonSerializer.Deserialize>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new List();
_logger.LogInformation("成功从 {FilePath} 加载 {Count} 个测试客户端配置。", _configsFilePath, _testClientConfigs.Count);
}
else
{
_logger.LogWarning("多个配置文件 {FilePath} 未找到,将创建空配置列表。", _configsFilePath);
_testClientConfigs = new List();
SaveTestClientConfigs();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "加载多个测试客户端配置文件时出错。将使用空配置列表。");
_testClientConfigs = new List();
}
}
///
/// 保存多个测试客户端配置到文件
///
private void SaveTestClientConfigs()
{
try
{
var options = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var json = JsonSerializer.Serialize(_testClientConfigs, options);
File.WriteAllText(_configsFilePath, json);
_logger.LogInformation("多个测试客户端配置已成功保存到 {FilePath},共 {Count} 个配置。", _configsFilePath, _testClientConfigs.Count);
}
catch (Exception ex)
{
_logger.LogError(ex, "保存多个测试客户端配置文件失败。");
}
}
///
/// 加载统计配置
///
private void LoadStatisticsConfig()
{
try
{
if (File.Exists(_statisticsConfigFilePath))
{
var json = File.ReadAllText(_statisticsConfigFilePath);
_globalStatisticsConfig = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new GlobalStatisticsConfig();
_logger.LogInformation("成功从 {FilePath} 加载统计配置。", _statisticsConfigFilePath);
}
else
{
_logger.LogWarning("统计配置文件 {FilePath} 未找到,将创建默认配置。", _statisticsConfigFilePath);
_globalStatisticsConfig = new GlobalStatisticsConfig();
SaveStatisticsConfig();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "加载统计配置文件时出错。将使用默认配置。");
_globalStatisticsConfig = new GlobalStatisticsConfig();
}
}
///
/// 保存统计配置到文件
///
private void SaveStatisticsConfig()
{
try
{
var options = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var json = JsonSerializer.Serialize(_globalStatisticsConfig, options);
File.WriteAllText(_statisticsConfigFilePath, json);
_logger.LogInformation("统计配置已成功保存到 {FilePath}。", _statisticsConfigFilePath);
}
catch (Exception ex)
{
_logger.LogError(ex, "保存统计配置文件失败。");
}
}
#endregion
#region 公共方法
///
/// 启动客户端
///
/// 客户端地址
/// 是否成功启动
public bool StartClient(string address)
{
_logger.LogInformation($"启动客户端: {address}");
ClientConfig config;
// 检查是否是测试客户端
var testConfig = _testClientConfigs.FirstOrDefault(c => c.Address == address);
if (testConfig != null)
{
config = testConfig;
_logger.LogInformation($"使用测试客户端配置: {config.Address}");
}
else
{
_logger.LogWarning($"客户端配置不存在: {address}");
return false;
}
// 如果客户端已存在,先停止
if (_clients.TryGetValue(address, out var existingClient))
{
existingClient.Stop();
_clients.TryRemove(address, out _);
}
var logger = _serviceProvider.GetService(typeof(ILogger)) as ILogger;
var client = new LTEClientWebSocket(config, logger!);
client.ConnectionOpened += (sender, e) => OnClientConnected(client);
client.ConnectionClosed += (sender, e) => OnClientDisconnected(client);
client.LogsReceived += (sender, logs) => OnLogsReceived(address, logs);
client.StateChanged += (sender, state) => OnStateChanged(address, state);
client.StatsReceived += (sender, data) => OnStatsReceived(address, data);
client.Start();
_clients[address] = client;
// 应用统计配置
UpdateClientStatisticsConfig(config.Name);
return true;
}
///
/// 停止客户端
///
/// 客户端地址
/// 是否成功停止
public bool StopClient(string address)
{
_logger.LogInformation($"停止客户端: {address}");
if (_clients.TryGetValue(address, out var client))
{
client.Stop();
_clients.TryRemove(address, out _);
return true;
}
return false;
}
///
/// 获取客户端状态
///
/// 客户端地址
/// 客户端状态
public ClientState? GetClientState(string address)
{
if (_clients.TryGetValue(address, out var client))
{
return client.State;
}
return null;
}
///
/// 获取所有客户端状态
///
/// 客户端状态字典
public Dictionary GetAllClientStates()
{
return _clients.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.State);
}
///
/// 获取客户端配置
///
/// 客户端名称
/// 客户端配置
public ClientConfig? GetClientConfig(string clientName)
{
return _testClientConfigs.FirstOrDefault(c => c.Name == clientName);
}
///
/// 获取所有客户端配置
///
/// 客户端配置列表
public List GetAllClientConfigs()
{
return _testClientConfigs.ToList();
}
///
/// 获取客户端日志
///
/// 客户端名称
/// 客户端日志列表
public List? GetClientLogs(string clientName)
{
if (_clients.TryGetValue(clientName, out var client))
{
return client.Client.Logs;
}
return null;
}
///
/// 重置客户端日志
///
/// 客户端名称
/// 是否成功重置
public bool ResetClientLogs(string clientName)
{
if (_clients.TryGetValue(clientName, out var client))
{
client.ResetLogs();
return true;
}
return false;
}
///
/// 设置客户端日志配置
///
/// 客户端名称
/// 日志配置
/// 是否成功设置
public bool SetClientLogsConfig(string clientName, ClientLogsConfig logsConfig)
{
if (_clients.TryGetValue(clientName, out var client))
{
client.SetLogsConfig(logsConfig, true);
return true;
}
return false;
}
///
/// 播放/暂停客户端
///
/// 客户端名称
/// 是否成功操作
public bool PlayPauseClient(string clientName)
{
if (_clients.TryGetValue(clientName, out var client))
{
client.PlayPause();
return true;
}
return false;
}
///
/// 发送消息到客户端
///
/// 客户端名称
/// 消息
/// 回调
/// 消息ID
public int SendMessageToClient(string clientName, JObject message, Action? callback = null)
{
if (_clients.TryGetValue(clientName, out var client))
{
return client.SendMessage(message, callback);
}
return -1;
}
///
/// 获取连接统计信息
///
/// 连接统计信息
public ConnectionStatistics GetConnectionStatistics()
{
var stats = new ConnectionStatistics
{
TotalClients = _clients.Count,
ConnectedClients = _clients.Values.Count(c => c.IsConnected),
DisconnectedClients = _clients.Values.Count(c => !c.IsConnected),
TotalLogs = _clients.Values.Sum(c => c.Client.LogCount),
ClientStates = GetAllClientStates()
};
return stats;
}
///
/// 停止所有客户端
///
public void StopAllClients()
{
foreach (var client in _clients.Values)
{
client.Stop();
}
_clients.Clear();
}
///
/// 启动所有已配置的客户端
///
public void StartAllConfiguredClients()
{
foreach (var config in _testClientConfigs)
{
if (config.Enabled)
{
StartClient(config.Address);
}
}
}
///
/// 获取客户端实例
///
/// 客户端地址
/// 客户端实例
public LTEClientWebSocket? GetClientInstance(string address)
{
_clients.TryGetValue(address, out var client);
return client;
}
///
/// 获取所有测试客户端配置
///
/// 测试客户端配置列表
public List GetAllTestClientConfigs()
{
return _testClientConfigs.ToList();
}
///
/// 获取默认测试客户端配置(第一个配置或创建默认配置)
///
/// 默认测试客户端配置
public ClientConfig GetDefaultTestClientConfig()
{
if (_testClientConfigs.Any())
{
return _testClientConfigs.First();
}
// 如果没有配置,创建默认配置
var defaultConfig = CreateDefaultTestConfig();
_testClientConfigs.Add(defaultConfig);
SaveTestClientConfigs();
return defaultConfig;
}
///
/// 设置测试客户端配置
///
/// 测试客户端配置
/// 是否成功设置
public bool SetTestClientConfig(ClientConfig config)
{
if (string.IsNullOrEmpty(config.Name))
{
_logger.LogWarning("尝试设置空名称的测试客户端配置");
return false;
}
if (string.IsNullOrEmpty(config.Address))
{
_logger.LogWarning("尝试设置空地址的测试客户端配置");
return false;
}
_logger.LogInformation($"更新测试客户端配置: {config.Name} (地址: {config.Address})");
// 使用Address作为唯一key来检查是否存在
var existingConfigIndex = _testClientConfigs.FindIndex(c => c.Address == config.Address);
if (existingConfigIndex >= 0)
{
// 更新现有配置
_testClientConfigs[existingConfigIndex] = config;
_logger.LogInformation($"更新现有测试配置 (地址: {config.Address})");
}
else
{
// 添加新配置
_testClientConfigs.Add(config);
_logger.LogInformation($"添加新测试配置 (地址: {config.Address})");
}
// 保存到文件
SaveTestClientConfigs();
return true;
}
///
/// 启动测试客户端
///
/// 是否成功启动
public bool StartTestClient()
{
var defaultConfig = GetDefaultTestClientConfig();
_logger.LogInformation("启动测试客户端: " + defaultConfig.Address);
return StartClient(defaultConfig.Address);
}
///
/// 停止测试客户端
///
/// 是否成功停止
public bool StopTestClient()
{
var defaultConfig = GetDefaultTestClientConfig();
_logger.LogInformation("停止测试客户端: " + defaultConfig.Address);
return StopClient(defaultConfig.Address);
}
///
/// 获取测试客户端实例
///
/// 测试客户端的WebSocket实例
public LTEClientWebSocket? GetTestClient()
{
var defaultConfig = GetDefaultTestClientConfig();
return GetClientInstance(defaultConfig.Address);
}
///
/// 获取所有测试客户端实例
///
/// 所有测试客户端的WebSocket实例列表
public List GetAllTestClients()
{
var testClients = new List();
foreach (var config in _testClientConfigs)
{
if (_clients.TryGetValue(config.Address, out var client))
{
testClients.Add(client);
}
}
return testClients;
}
///
/// 获取所有测试客户端配置和状态
///
/// 测试客户端配置和状态列表
public List GetAllTestClientsWithState()
{
var result = new List();
foreach (var config in _testClientConfigs)
{
var client = GetClientInstance(config.Address);
var state = client?.State ?? ClientState.Stop;
result.Add(new { Config = config, State = state, Client = client });
}
return result;
}
///
/// 创建默认测试配置
///
/// 默认测试配置
private ClientConfig CreateDefaultTestConfig()
{
var layers = new Dictionary();
foreach(var layerName in LogLayerTypes.AllLayers.Where(l => l != "EVENT"))
{
layers[layerName] = new LogLayerConfig { Level = LogLayerTypes.GetDefaultLevel(layerName), Filter = "warn", MaxSize = 1000, Payload = false };
}
// Set some specific payloads to true
if(layers.ContainsKey("PHY")) layers["PHY"].Payload = true;
if(layers.ContainsKey("MAC")) layers["MAC"].Payload = true;
if(layers.ContainsKey("RRC")) layers["RRC"].Payload = true;
if(layers.ContainsKey("NAS")) layers["NAS"].Payload = true;
return new ClientConfig
{
Name = "TestClient",
Enabled = true,
Address = "192.168.13.12:9001",
Ssl = false,
ReconnectDelay = 15000,
Password = "test123",
Logs = new ClientLogsConfig
{
Layers = layers,
Signal = true,
Cch = true
}
};
}
///
/// 根据地址获取测试客户端配置
///
/// 服务器地址
/// 测试客户端配置
public ClientConfig? GetTestClientConfigByAddress(string address)
{
return _testClientConfigs.FirstOrDefault(c => c.Address == address);
}
///
/// 删除测试客户端配置
///
/// 服务器地址
/// 是否成功删除
public bool RemoveTestClientConfig(string address)
{
var config = _testClientConfigs.FirstOrDefault(c => c.Address == address);
if (config != null)
{
_testClientConfigs.Remove(config);
SaveTestClientConfigs();
_logger.LogInformation($"删除测试客户端配置 (地址: {address})");
return true;
}
return false;
}
///
/// 获取当前缓存的日志
///
public IEnumerable GetLogCache()
{
// 使用线程安全的方式获取日志列表
lock (_logCache)
{
var logs = _logCache.ToList();
_logger.LogDebug("GetLogCache: 返回 {Count} 条日志", logs.Count);
return logs;
}
}
///
/// 获取当前缓存的日志总数
///
public int GetLogCacheCount()
{
var count = _logCache.Count;
_logger.LogDebug("GetLogCacheCount: 当前缓存 {Count} 条日志", count);
return count;
}
///
/// 清空日志缓存
///
public void ClearLogCache()
{
_logger.LogInformation("清空日志缓存");
lock (_logCache)
{
while (_logCache.TryDequeue(out _))
{
// 清空所有日志
}
}
}
///
/// 重置日志缓存(清空并重新初始化)
///
public void ResetLogCache()
{
_logger.LogInformation("重置日志缓存");
ClearLogCache();
// 可以在这里添加其他重置逻辑
}
///
/// 手动添加日志到缓存
///
/// 日志对象
public void AddLogToCache(LTELog log)
{
if (log != null)
{
lock (_logCache)
{
_logCache.Enqueue(log);
_logger.LogDebug("手动添加日志到缓存: {Layer} - {Message}", log.Layer, log.Message);
// 维持缓存大小
while (_logCache.Count > LogCacheSize)
{
_logCache.TryDequeue(out _);
}
}
}
}
///
/// 手动添加多个日志到缓存
///
/// 日志列表
public void AddLogsToCache(List logs)
{
if (logs != null && logs.Any())
{
lock (_logCache)
{
foreach (var log in logs)
{
_logCache.Enqueue(log);
}
_logger.LogInformation("手动添加 {Count} 条日志到缓存", logs.Count);
// 维持缓存大小
while (_logCache.Count > LogCacheSize)
{
_logCache.TryDequeue(out _);
}
}
}
}
///
/// 获取日志缓存详细状态(调试用)
///
/// 缓存状态信息
public object GetLogCacheStatus()
{
lock (_logCache)
{
var logs = _logCache.ToList();
var sampleLogs = logs.TakeLast(3).Select(log => new
{
timestamp = log.Timestamp,
layer = log.Layer,
message = log.Message?.Substring(0, Math.Min(50, log.Message?.Length ?? 0)) + "..."
}).ToList();
return new
{
totalCount = _logCache.Count,
actualCount = logs.Count,
cacheSize = LogCacheSize,
sampleLogs = sampleLogs,
timestamp = DateTime.UtcNow
};
}
}
#region 统计相关方法
///
/// 获取所有统计数据
///
public List GetAllStatistics()
{
return _statisticsService.GetAllStats();
}
///
/// 获取最新的统计数据
///
public StatisticsData? GetLatestStatistics()
{
return _statisticsService.GetLatestStats();
}
///
/// 获取指定客户端的最新统计数据
///
public StatisticsData? GetClientStatistics(string clientName)
{
return _statisticsService.GetLatestStatsByClient(clientName);
}
///
/// 获取指定客户端的历史统计数据
///
public List GetClientStatisticsHistory(string clientName)
{
return _statisticsService.GetStatsHistoryByClient(clientName);
}
///
/// 获取所有客户端的最新统计数据
///
public Dictionary GetAllClientStatistics()
{
return _statisticsService.GetAllLatestStats();
}
///
/// 清空统计数据
///
public void ClearStatistics()
{
_statisticsService.ClearStats();
}
///
/// 获取统计摘要
///
public object GetStatisticsSummary()
{
return _statisticsService.GetSummary();
}
///
/// 获取SSE格式的统计数据
///
public string GetStatisticsAsSSE()
{
return _statisticsService.GetStatsAsSSE();
}
///
/// 获取指定客户端的SSE格式统计数据
///
public string GetClientStatisticsAsSSE(string clientName)
{
return _statisticsService.GetClientStatsAsSSE(clientName);
}
///
/// 获取统计队列大小
///
public int GetStatisticsQueueCount()
{
return _statisticsService.GetQueueCount();
}
///
/// 获取统计客户端数量
///
public int GetStatisticsClientCount()
{
return _statisticsService.GetClientCount();
}
///
/// 获取全局统计配置
///
/// 全局统计配置
public GlobalStatisticsConfig GetGlobalStatisticsConfig()
{
return _globalStatisticsConfig;
}
///
/// 设置全局统计配置
///
/// 统计配置
public void SetGlobalStatisticsConfig(GlobalStatisticsConfig config)
{
_globalStatisticsConfig = config;
SaveStatisticsConfig();
// 更新所有客户端的统计配置
UpdateAllClientsStatisticsConfig();
}
///
/// 获取指定客户端的统计配置
///
/// 客户端名称
/// 统计配置
public StatisticsConfig? GetClientStatisticsConfig(string clientName)
{
return _globalStatisticsConfig.ClientConfigs.FirstOrDefault(c => c.ClientName == clientName);
}
///
/// 设置指定客户端的统计配置
///
/// 统计配置
public void SetClientStatisticsConfig(StatisticsConfig config)
{
var existingConfig = _globalStatisticsConfig.ClientConfigs.FirstOrDefault(c => c.ClientName == config.ClientName);
if (existingConfig != null)
{
_globalStatisticsConfig.ClientConfigs.Remove(existingConfig);
}
_globalStatisticsConfig.ClientConfigs.Add(config);
SaveStatisticsConfig();
// 更新指定客户端的统计配置
UpdateClientStatisticsConfig(config.ClientName);
}
///
/// 根据IP地址获取统计配置
///
/// IP地址
/// 统计配置
public StatisticsConfig? GetStatisticsConfigByIp(string ipAddress)
{
return _globalStatisticsConfig.ClientConfigs.FirstOrDefault(c => c.IpAddress == ipAddress);
}
///
/// 更新所有客户端的统计配置
///
private void UpdateAllClientsStatisticsConfig()
{
foreach (var client in _clients.Values)
{
UpdateClientStatisticsConfig(client.Config.Name);
}
}
///
/// 更新指定客户端的统计配置
///
/// 客户端名称
private void UpdateClientStatisticsConfig(string clientName)
{
if (_clients.TryGetValue(clientName, out var client))
{
var config = GetClientStatisticsConfig(clientName);
if (config != null && config.IsEnabled)
{
client.SetStatisticsConfig(config.EnableSamples, config.EnableRf);
}
else
{
// 使用默认配置
client.SetStatisticsConfig(_globalStatisticsConfig.DefaultSamples, _globalStatisticsConfig.DefaultRf);
}
}
}
#endregion
#endregion
#region 私有方法
///
/// 客户端连接事件处理
///
private void OnClientConnected(LTEClientWebSocket client)
{
_logger.LogInformation($"客户端已连接: {client.Client.Config.Address}");
ClientConnected?.Invoke(this, client);
}
///
/// 客户端断开事件处理
///
private void OnClientDisconnected(LTEClientWebSocket client)
{
_logger.LogWarning($"客户端已断开: {client.Client.Config.Address}");
ClientDisconnected?.Invoke(this, client);
}
///
/// 日志接收事件处理
///
private void OnLogsReceived(string clientName, List logs)
{
_logger.LogInformation($"客户端 {clientName} 收到日志: {logs.Count} 条");
if (logs != null && logs.Any())
{
lock (_logCache)
{
// 将新日志存入中央缓存
foreach (var log in logs)
{
if (log != null)
{
_logCache.Enqueue(log);
_logger.LogDebug($"客户端 {clientName} 添加日志到缓存: {log.Layer} - {log.Message}");
}
}
// 维持缓存大小
while (_logCache.Count > LogCacheSize)
{
_logCache.TryDequeue(out _);
}
_logger.LogInformation($"客户端 {clientName} 日志已添加到缓存,当前缓存总数: {_logCache.Count}");
}
}
LogsReceived?.Invoke(this, (clientName, logs));
}
///
/// 状态变化事件处理
///
private void OnStateChanged(string clientName, ClientState state)
{
_logger.LogInformation($"客户端 {clientName} 状态变更: {state}");
StateChanged?.Invoke(this, (clientName, state));
}
///
/// 状态变化事件处理
///
private void OnStatsReceived(string clientName, JObject data)
{
_logger.LogInformation($"客户端 {clientName} 收到统计数据: {data.ToString()}");
// 处理统计数据
_statisticsService.ProcessStatsData(data, clientName);
}
#endregion
}
///
/// 连接统计信息
///
public class ConnectionStatistics
{
///
/// 总客户端数
///
public int TotalClients { get; set; }
///
/// 已连接客户端数
///
public int ConnectedClients { get; set; }
///
/// 未连接客户端数
///
public int DisconnectedClients { get; set; }
///
/// 总日志数
///
public int TotalLogs { get; set; }
///
/// 客户端状态字典
///
public Dictionary ClientStates { get; set; } = new();
}
}