refactor: 枚举移入Models目录,命名空间更新为Rainbow.Entity.Models
大石头 authored at 2026-07-02 12:54:58
5.94 KiB
RainbowBridge
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Rainbow.Services;

/// <summary>Windows 网络流量统计提供者。通过 Get-NetAdapterStatistics PowerShell 采集</summary>
public class WindowsNetworkStatProvider : INetworkStatProvider
{
    /// <summary>获取所有网口的流量统计数据</summary>
    public async Task<List<InterfaceStatData>> GetInterfaceStatsAsync()
    {
        var result = new List<InterfaceStatData>();

        try
        {
            // PowerShell Get-NetAdapterStatistics 获取网口统计
            var psi = new ProcessStartInfo("powershell",
                "-Command \"Get-NetAdapterStatistics | Select-Object Name, ReceivedBytes, SentBytes, ReceivedPackets, SentPackets, ReceivedErrors, SentErrors | ConvertTo-Json\"")
            {
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true,
            };
            using var proc = Process.Start(psi);
            if (proc == null) return result;

            var output = await proc.StandardOutput.ReadToEndAsync();
            await proc.WaitForExitAsync().WaitAsync(TimeSpan.FromSeconds(15));

            if (String.IsNullOrEmpty(output)) return result;

            // 简单 JSON 解析(不依赖 Newtonsoft.Json)
            var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

            // 处理单个对象或数组
            var items = output.TrimStart();
            if (items.StartsWith("["))
            {
                // JSON 数组
                var depth = 0;
                var start = 0;
                for (var i = 0; i < items.Length; i++)
                {
                    if (items[i] == '{')
                    {
                        if (depth == 0) start = i;
                        depth++;
                    }
                    else if (items[i] == '}')
                    {
                        depth--;
                        if (depth == 0 && start < i)
                        {
                            var obj = items.Substring(start, i - start + 1);
                            var stat = ParseStatObject(obj, timestamp);
                            if (stat != null) result.Add(stat);
                            start = i + 1;
                        }
                    }
                }
            }
            else if (items.StartsWith("{"))
            {
                var stat = ParseStatObject(items, timestamp);
                if (stat != null) result.Add(stat);
            }
        }
        catch
        {
            // 异常时返回空列表
        }

        return result;
    }

    /// <summary>获取当前系统总连接数</summary>
    public Int32 GetConnectionCount()
    {
        try
        {
            var psi = new ProcessStartInfo("netstat", "-an")
            {
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true,
            };
            using var proc = Process.Start(psi);
            if (proc == null) return 0;

            var output = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit(5000);

            var count = 0;
            foreach (var line in output.Split('\n'))
            {
                if (line.Trim().Contains("ESTABLISHED"))
                    count++;
            }
            return count;
        }
        catch
        {
            return 0;
        }
    }

    /// <summary>从 PowerShell JSON 对象中解析网口统计数据</summary>
    private static InterfaceStatData? ParseStatObject(String json, Int64 timestamp)
    {
        try
        {
            var name = ExtractJsonValue(json, "Name") ?? "";
            var rxBytes = ParseLong(ExtractJsonValue(json, "ReceivedBytes"));
            var txBytes = ParseLong(ExtractJsonValue(json, "SentBytes"));
            var rxPackets = ParseLong(ExtractJsonValue(json, "ReceivedPackets"));
            var txPackets = ParseLong(ExtractJsonValue(json, "SentPackets"));
            var rxErrors = ParseLong(ExtractJsonValue(json, "ReceivedErrors"));
            var txErrors = ParseLong(ExtractJsonValue(json, "SentErrors"));

            if (String.IsNullOrEmpty(name)) return null;

            return new InterfaceStatData
            {
                Name = name,
                RxBytes = rxBytes,
                TxBytes = txBytes,
                RxPackets = rxPackets,
                TxPackets = txPackets,
                RxErrors = rxErrors,
                TxErrors = txErrors,
                Timestamp = timestamp,
            };
        }
        catch
        {
            return null;
        }
    }

    /// <summary>从简化的 JSON 中提取字段值(无 Newtonsoft.Json 依赖)</summary>
    private static String? ExtractJsonValue(String json, String key)
    {
        var search = $"\"{key}\":";
        var idx = json.IndexOf(search, StringComparison.OrdinalIgnoreCase);
        if (idx < 0) return null;

        var start = idx + search.Length;
        // 跳过空白
        while (start < json.Length && json[start] == ' ') start++;
        if (start >= json.Length) return null;

        if (json[start] == '"')
        {
            // 字符串值
            start++;
            var end = json.IndexOf('"', start);
            return end > start ? json.Substring(start, end - start) : null;
        }
        else
        {
            // 数值或 null
            var end = start;
            while (end < json.Length && json[end] != ',' && json[end] != '}' && json[end] != '\n' && json[end] != '\r')
                end++;
            var val = json.Substring(start, end - start).Trim();
            return val == "null" ? null : val;
        }
    }

    private static Int64 ParseLong(String? value)
    {
        if (String.IsNullOrEmpty(value)) return 0;
        return Int64.TryParse(value, out var result) ? result : 0;
    }
}