A:恢复代码

This commit is contained in:
jimmy committed 2025-08-17 19:26:24 +08:00
1 parent a53ad0ab18
commit 5f3d6eda5b
6 files changed
+412 -38

No files matched your search

@@ -10,11 +10,14 @@ using Data;
using Data.Models;
using Data.Repositories;
using Shell.Utils;
using Shell.Services;
namespace Shell.Controllers;
public class NetworkController : BaseController
{
private static ServerStartupManager? _serverManager;
public async Task GetInterfacesAsync(HttpContext context)
{
try
@@ -110,7 +113,8 @@ public class NetworkController : BaseController
var availableRanges = new List<object>();
var now = DateTimeOffset.UtcNow;
var hasHourlyData = await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("hourly", now.AddHours(-1).ToUnixTimeSeconds());
var hasHourlyData =
await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("hourly", now.AddHours(-1).ToUnixTimeSeconds());
if (hasHourlyData)
{
availableRanges.Add(new
@@ -122,7 +126,8 @@ public class NetworkController : BaseController
});
}
var hasDailyData = await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("daily", now.AddDays(-1).ToUnixTimeSeconds());
var hasDailyData =
await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("daily", now.AddDays(-1).ToUnixTimeSeconds());
if (hasDailyData)
{
availableRanges.Add(new
@@ -134,7 +139,8 @@ public class NetworkController : BaseController
});
}
var hasWeeklyData = await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("daily", now.AddDays(-7).ToUnixTimeSeconds());
var hasWeeklyData =
await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("daily", now.AddDays(-7).ToUnixTimeSeconds());
if (hasWeeklyData)
{
availableRanges.Add(new
@@ -146,7 +152,8 @@ public class NetworkController : BaseController
});
}
var hasMonthlyData = await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("daily", now.AddDays(-30).ToUnixTimeSeconds());
var hasMonthlyData =
await NetworkApiHelper.HasNetworkDataInTimeRangeAsync("daily", now.AddDays(-30).ToUnixTimeSeconds());
if (hasMonthlyData)
{
availableRanges.Add(new
@@ -218,7 +225,8 @@ public class NetworkController : BaseController
_ => (now.AddHours(-1).ToUnixTimeSeconds(), "hour")
};
var points = await NetworkApiHelper.GetTrafficTrendsAsync(mappedTimeRange, interfaceId, startTime, now.ToUnixTimeSeconds());
var points = await NetworkApiHelper.GetTrafficTrendsAsync(mappedTimeRange, interfaceId, startTime,
now.ToUnixTimeSeconds());
await WriteJsonResponseAsync(context, new ResponseModel<object>
{
@@ -307,4 +315,93 @@ public class NetworkController : BaseController
await WriteErrorResponseAsync(context, $"获取Top应用流量数据失败: {ex.Message}", 500);
}
}
}
/// <summary>
/// 获取实时网络统计数据
/// </summary>
public async Task GetRealTimeStatsAsync(HttpContext context)
{
try
{
if (_serverManager == null)
{
await WriteErrorResponseAsync(context, "网络监控服务未启动", 503);
return;
}
// 获取所有活跃进程的实时统计
var activeProcessStats = _serverManager.GetAllActiveProcessStats();
// 计算总体统计
var totalUploadSpeed = activeProcessStats.Sum(s => s.BytesOutPerSecond);
var totalDownloadSpeed = activeProcessStats.Sum(s => s.BytesInPerSecond);
var totalSpeed = totalUploadSpeed + totalDownloadSpeed;
// 格式化进程列表
var processes = activeProcessStats.OrderByDescending(s => s.TotalBytesPerSecond)
.Take(20) // 只返回前20个活跃进程
.Select(s => new
{
processId = s.ProcessId,
processName = s.ProcessName,
connectionCount = s.ConnectionCount,
bytesInPerSecond = s.BytesInPerSecond,
bytesOutPerSecond = s.BytesOutPerSecond,
totalBytesPerSecond = s.TotalBytesPerSecond,
formattedDownloadSpeed = s.FormattedDownloadSpeed,
formattedUploadSpeed = s.FormattedUploadSpeed,
formattedTotalSpeed = s.FormattedTotalSpeed,
lastUpdate = s.LastUpdate
}).ToList();
var result = new
{
timestamp = DateTime.Now,
summary = new
{
totalUploadSpeed = totalUploadSpeed,
totalDownloadSpeed = totalDownloadSpeed,
totalSpeed = totalSpeed,
formattedUploadSpeed = FormatSpeed(totalUploadSpeed),
formattedDownloadSpeed = FormatSpeed(totalDownloadSpeed),
formattedTotalSpeed = FormatSpeed(totalSpeed),
activeProcessCount = activeProcessStats.Count
},
processes = processes
};
await WriteJsonResponseAsync(context, new ResponseModel<object>
{
Success = true,
Data = result,
Message = "获取实时网络统计成功"
});
}
catch (Exception ex)
{
await WriteErrorResponseAsync(context, $"获取实时网络统计失败: {ex.Message}", 500);
}
}
/// <summary>
/// 设置ServerStartupManager实例(供启动时调用)
/// </summary>
public static void SetServerManager(ServerStartupManager serverManager)
{
_serverManager = serverManager;
}
/// <summary>
/// 格式化网速显示
/// </summary>
private static string FormatSpeed(double bytesPerSec)
{
if (bytesPerSec >= 1024 * 1024 * 1024)
return $"{bytesPerSec / (1024.0 * 1024 * 1024):F1} GB/s";
if (bytesPerSec >= 1024 * 1024)
return $"{bytesPerSec / (1024.0 * 1024):F1} MB/s";
if (bytesPerSec >= 1024)
return $"{bytesPerSec / 1024.0:F1} KB/s";
return $"{bytesPerSec:F0} B/s";
}
}
@@ -34,10 +34,7 @@ public class ApiRouteManager : IDisposable
_server.UseMiddleware(Middlewares.Cors);
// 基础API
_server.Get("/api", async (context) =>
{
await context.Response.WriteJsonAsync(new { message = "Hi!" });
});
_server.Get("/api", async (context) => { await context.Response.WriteJsonAsync(new { message = "Hi!" }); });
// 订阅相关API
RegisterSubscriptionRoutes();
@@ -120,6 +117,7 @@ public class ApiRouteManager : IDisposable
_server.Get("/api/realtime/active-apps", _systemController.GetActiveAppsAsync);
_server.Get("/api/system/info", _systemController.GetSystemInfoAsync);
_server.Get("/api/system/collection-stats", _systemController.GetCollectionStatsAsync);
_server.Get("/api/network/realtime-stats", _networkController.GetRealTimeStatsAsync);
}
private void RegisterAppAnalysisRoutes()
@@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Application;
using Application.Utils;
@@ -8,6 +11,12 @@ using Common.Net.WebSocketConn;
using Common.Utils;
using Utils.ETW.Etw;
using Utils.ETW.Core;
using Utils.ETW.Models;
using Infrastructure.Models;
using Infrastructure.utils;
using Data;
using Data.Models;
using Shell.Controllers;
namespace Shell.Services;
@@ -16,6 +25,7 @@ public class ServerStartupManager
private readonly ApiRouteManager _apiRouteManager;
private readonly StaticFileServer _staticFileServer;
private HighPrecisionNetworkMonitor? _networkMonitor;
private EnhancedEtwNetworkManager? _etwNetworkManager;
public ServerStartupManager()
{
@@ -57,7 +67,15 @@ public class ServerStartupManager
// 启动监控
_networkMonitor.Start();
// 同时启动ETW监控以确保兼容性和数据完整性
_etwNetworkManager = new EnhancedEtwNetworkManager();
_etwNetworkManager.StartMonitoring();
Log.Info("高精度网络监控已启动 - 基于TCP连接表方案,解决ETW突发流量统计不准确问题");
Log.Info("ETW网络监控已启动 - 确保数据完整性和兼容性");
// 设置NetworkController的ServerManager引用
NetworkController.SetServerManager(this);
}
catch (Exception ex)
{
@@ -117,6 +135,8 @@ public class ServerStartupManager
_apiRouteManager?.Stop();
_networkMonitor?.Stop();
_networkMonitor?.Dispose();
_etwNetworkManager?.StopMonitoring();
_etwNetworkManager?.Dispose();
}
#region 网络监控事件处理器
@@ -124,25 +144,109 @@ public class ServerStartupManager
/// <summary>
/// 处理单个进程的网络统计更新
/// </summary>
private void OnProcessNetworkStatsUpdated(HighPrecisionNetworkMonitor.ProcessNetworkStats stats)
private async void OnProcessNetworkStatsUpdated(HighPrecisionNetworkMonitor.ProcessNetworkStats stats)
{
// 可以在这里将统计数据推送给前端或写入数据库
Log.Debug($"进程网络统计更新: {stats}");
try
{
// 将统计数据推送给前端
var networkData = new
{
type = "process_network_stats",
data = new
{
processId = stats.ProcessId,
processName = stats.ProcessName,
connectionCount = stats.ConnectionCount,
bytesInPerSecond = stats.BytesInPerSecond,
bytesOutPerSecond = stats.BytesOutPerSecond,
totalBytesPerSecond = stats.TotalBytesPerSecond,
formattedDownloadSpeed = stats.FormattedDownloadSpeed,
formattedUploadSpeed = stats.FormattedUploadSpeed,
formattedTotalSpeed = stats.FormattedTotalSpeed,
lastUpdate = stats.LastUpdate
}
};
// 示例:通过WebSocket推送给前端
// WebSocketManager.Instance.BroadcastMessage("network_stats", stats);
// 通过WebSocket推送给前端
var message = new Common.Net.WebSocketConn.ResponseMessage
{
Type = "network_stats",
Data = networkData,
Success = true
};
await WebSocketManager.Instance.BroadcastMessage(message);
// 更新到GlobalNetworkMonitor以保持兼容性
UpdateGlobalNetworkMonitorWithStats(stats);
Log.Debug($"进程网络统计更新: {stats}");
}
catch (Exception ex)
{
Log.Error($"处理进程网络统计更新时出错: {ex.Message}");
}
}
/// <summary>
/// 处理所有活跃进程的网络统计批量更新
/// </summary>
private void OnAllProcessStatsUpdated(List<HighPrecisionNetworkMonitor.ProcessNetworkStats> statsList)
private async void OnAllProcessStatsUpdated(List<HighPrecisionNetworkMonitor.ProcessNetworkStats> statsList)
{
Log.Debug($"批量网络统计更新: {statsList.Count} 个活跃进程");
try
{
Log.Debug($"批量网络统计更新: {statsList.Count} 个活跃进程");
// 示例:可以在这里进行数据聚合或向前端推送汇总信息
var totalSpeed = statsList.Sum(s => s.TotalBytesPerSecond);
Log.Info($"系统总网速: {FormatSpeed(totalSpeed)}");
// 计算系统总流量
var totalUploadSpeed = statsList.Sum(s => s.BytesOutPerSecond);
var totalDownloadSpeed = statsList.Sum(s => s.BytesInPerSecond);
var totalSpeed = totalUploadSpeed + totalDownloadSpeed;
// 创建全局网络统计数据
var globalStats = new
{
type = "global_network_stats",
data = new
{
activeProcessCount = statsList.Count,
totalUploadSpeed = totalUploadSpeed,
totalDownloadSpeed = totalDownloadSpeed,
totalSpeed = totalSpeed,
formattedUploadSpeed = FormatSpeed(totalUploadSpeed),
formattedDownloadSpeed = FormatSpeed(totalDownloadSpeed),
formattedTotalSpeed = FormatSpeed(totalSpeed),
timestamp = DateTime.Now,
topProcesses = statsList.OrderByDescending(s => s.TotalBytesPerSecond)
.Take(5)
.Select(s => new
{
processId = s.ProcessId,
processName = s.ProcessName,
speed = s.TotalBytesPerSecond,
formattedSpeed = s.FormattedTotalSpeed
})
.ToList()
}
};
// 推送全局统计给前端
var globalMessage = new Common.Net.WebSocketConn.ResponseMessage
{
Type = "global_network_stats",
Data = globalStats,
Success = true
};
await WebSocketManager.Instance.BroadcastMessage(globalMessage);
// 存储全局网络数据到数据库
_ = Task.Run(() => SaveGlobalNetworkStatsAsync(totalUploadSpeed, totalDownloadSpeed));
Log.Info(
$"系统总网速: {FormatSpeed(totalSpeed)} (↑{FormatSpeed(totalUploadSpeed)} ↓{FormatSpeed(totalDownloadSpeed)})");
}
catch (Exception ex)
{
Log.Error($"处理批量网络统计更新时出错: {ex.Message}");
}
}
/// <summary>
@@ -188,5 +292,68 @@ public class ServerStartupManager
new List<HighPrecisionNetworkMonitor.ProcessNetworkStats>();
}
/// <summary>
/// 更新GlobalNetworkMonitor以保持兼容性
/// </summary>
private void UpdateGlobalNetworkMonitorWithStats(HighPrecisionNetworkMonitor.ProcessNetworkStats stats)
{
try
{
// 创建一个NetworkModel来更新GlobalNetworkMonitor
var networkModel = new NetworkModel
{
ProcessId = (int)stats.ProcessId,
ThreadId = 0, // 使用默认值
ProcessName = stats.ProcessName,
SourceIp = IPAddress.Loopback, // 使用默认值
DestinationIp = IPAddress.Loopback, // 使用默认值
SourcePort = 0, // 使用默认值
DestinationPort = 0, // 使用默认值
ConnectType = ProtocolType.TCP, // 使用TCP
IsPartialConnection = false, // 使用默认值
BytesSent = (long)stats.BytesOutPerSecond, // 当前秒的发送字节数
BytesReceived = (long)stats.BytesInPerSecond, // 当前秒的接收字节数
LastSeenTime = DateTime.Now,
RecordTime = stats.LastUpdate,
IsIncrementalData = true,
State = ConnectionState.Connected
};
// 更新到GlobalNetworkMonitor
GlobalNetworkMonitor.Instance.UpdateConnectionInfo(networkModel);
}
catch (Exception ex)
{
Log.Error($"更新GlobalNetworkMonitor时出错: {ex.Message}");
}
}
/// <summary>
/// 异步保存全局网络统计到数据库
/// </summary>
private async Task SaveGlobalNetworkStatsAsync(double uploadSpeed, double downloadSpeed)
{
try
{
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
// 创建全局网络记录
var globalNetwork = new GlobalNetwork
{
Timestep = timestamp,
Upload = (long)uploadSpeed,
Download = (long)downloadSpeed,
NetworkCardGuid = "system_total" // 使用固定值表示系统总计
};
// 保存到数据库
await DatabaseManager.Instance.Networks.SaveGlobalNetworkAsync(globalNetwork);
}
catch (Exception ex)
{
Log.Error($"保存全局网络统计到数据库时出错: {ex.Message}");
}
}
#endregion
}
}
@@ -17,7 +17,8 @@ public partial class WebPanel : System.Windows.Controls.UserControl
// Class1.Main2();
InitWebView();
// 延迟初始化WebView,避免构造函数中的异步调用
this.Loaded += WebPanel_Loaded;
// 注册管理 WebSocket 事件
// WebSocketManger();
@@ -27,6 +28,18 @@ public partial class WebPanel : System.Windows.Controls.UserControl
// NewMethod();
}
private async void WebPanel_Loaded(object sender, RoutedEventArgs e)
{
try
{
await InitWebViewAsync();
}
catch (Exception ex)
{
Log.Error($"WebView初始化失败: {ex.Message}");
}
}
private static async Task NewMethod()
{
if (!SysHelper.IsAdministrator())
@@ -61,7 +74,7 @@ public partial class WebPanel : System.Windows.Controls.UserControl
});
}
private async void InitWebView()
private async Task InitWebViewAsync()
{
// 初始化 WebView2
await webView.EnsureCoreWebView2Async();
@@ -11,8 +11,8 @@
Width="1200"
MinHeight="600"
MinWidth="800"
WindowStartupLocation="CenterScreen"
Icon="pack://application:,,,/Assets/Icons/app.ico">
<userControls:WebPanel x:Name="WebPanel" />
WindowStartupLocation="CenterScreen">
<Border x:Name="WebContainer">
</Border>
</Window>
@@ -3,7 +3,10 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Windows;
using System.Windows.Controls;
using Common.Logger;
using Shell.UserControls;
using Shell.Utils;
namespace Shell.Views;
@@ -11,11 +14,11 @@ public partial class TrafficAnalysisWindow : Window
{
private static TrafficAnalysisWindow? _instance;
private static bool _hasRequestedElevation = false;
// Win32 API for checking admin rights
[DllImport("shell32.dll")]
static extern bool IsUserAnAdmin();
public static TrafficAnalysisWindow Instance
{
get
@@ -28,7 +31,7 @@ public partial class TrafficAnalysisWindow : Window
return _instance;
}
}
private TrafficAnalysisWindow()
{
InitializeComponent();
@@ -37,7 +40,7 @@ public partial class TrafficAnalysisWindow : Window
Log.Info("TrafficAnalysisWindow 初始化");
}
public static void ShowWindow()
{
try
@@ -75,7 +78,7 @@ public partial class TrafficAnalysisWindow : Window
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private static bool IsRunningAsAdmin()
{
try
@@ -90,7 +93,7 @@ public partial class TrafficAnalysisWindow : Window
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
private static void RequestElevation()
{
try
@@ -116,12 +119,108 @@ public partial class TrafficAnalysisWindow : Window
_hasRequestedElevation = true; // Don't ask again in this session
}
}
private void TrafficAnalysisWindow_Loaded(object sender, RoutedEventArgs e)
private async void TrafficAnalysisWindow_Loaded(object sender, RoutedEventArgs e)
{
Log.Info("TrafficAnalysisWindow 加载完成");
try
{
Log.Info("TrafficAnalysisWindow 加载完成");
// 更新状态
// 检查WebView2是否可用
bool hasWebView2 = await WebView2Helper.IsWebView2RuntimeInstalled();
if (hasWebView2)
{
// 创建WebPanel并添加到容器
var webPanel = new WebPanel();
WebContainer.Child = webPanel;
}
else
{
// 显示简化的错误界面
var errorPanel = CreateErrorPanel();
WebContainer.Child = errorPanel;
}
}
catch (Exception ex)
{
Log.Error($"TrafficAnalysisWindow加载时发生错误: {ex.Message}");
// 显示错误界面
var errorPanel = CreateErrorPanel(ex.Message);
WebContainer.Child = errorPanel;
}
}
private StackPanel CreateErrorPanel(string errorMessage = null)
{
var panel = new StackPanel
{
Margin = new Thickness(20),
VerticalAlignment = System.Windows.VerticalAlignment.Center,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center
};
panel.Children.Add(new TextBlock
{
Text = "⚠️ 流量分析功能不可用",
FontSize = 18,
FontWeight = FontWeights.Bold,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
Margin = new Thickness(0, 0, 0, 20)
});
if (string.IsNullOrEmpty(errorMessage))
{
panel.Children.Add(new TextBlock
{
Text = "需要安装 Microsoft Edge WebView2 运行时才能使用此功能。",
FontSize = 14,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
Margin = new Thickness(0, 0, 0, 10),
TextWrapping = TextWrapping.Wrap
});
var downloadButton = new System.Windows.Controls.Button
{
Content = "下载 WebView2 运行时",
Padding = new Thickness(15, 8, 15, 8),
HorizontalAlignment = System.Windows.HorizontalAlignment.Center
};
downloadButton.Click += (s, e) =>
{
try
{
Process.Start(new ProcessStartInfo
{
FileName = "https://go.microsoft.com/fwlink/p/?LinkId=2124703",
UseShellExecute = true
});
}
catch (Exception ex)
{
Log.Error($"无法打开下载链接: {ex.Message}");
}
};
panel.Children.Add(downloadButton);
}
else
{
panel.Children.Add(new TextBlock
{
Text = $"错误信息: {errorMessage}",
FontSize = 12,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
Foreground = System.Windows.Media.Brushes.Red,
TextWrapping = TextWrapping.Wrap
});
}
return panel;
}
private void TrafficAnalysisWindow_Closing(object sender, CancelEventArgs e)
{
// Don't actually close, just hide the window for better performance
@@ -129,7 +228,7 @@ public partial class TrafficAnalysisWindow : Window
this.Hide();
Log.Info("TrafficAnalysisWindow 隐藏");
}
// Force close method for application shutdown
public void ForceClose()
{