using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Diagnostics.Tracing.Parsers; using Microsoft.Diagnostics.Tracing.Session; using Netch.Controllers; using Netch.Forms; using Netch.Models; namespace Netch.Utils { public static class Bandwidth { public static int received; /// /// 计算流量 /// /// 流量 /// 带单位的流量字符串 public static string Compute(long bandwidth) { string[] units = { "KB", "MB", "GB", "TB", "PB" }; double result = bandwidth; var i = -1; do { i++; } while ((result /= 1024) > 1024); if (result < 0) { result = 0; } return string.Format("{0} {1}", Math.Round(result, 2), units[i]); } /// /// 根据程序名统计流量 /// /// public static void NetTraffic(Server server, Mode mode, MainController mainController) { var counterLock = new object(); //int sent = 0; //var processList = Process.GetProcessesByName(ProcessName).Select(p => p.Id).ToHashSet(); var processList = new List(); if (server.Type.Equals("Socks5") && mainController.pHTTPController != null) { processList.Add(mainController.pHTTPController.pPrivoxyController.Instance.Id); } else if (server.Type.Equals("SS") && Global.Settings.BootShadowsocksFromDLL) { processList.Add(Process.GetCurrentProcess().Id); } else if (mainController.pServerClientController != null) { // mainController.pServerClientController.Instance processList.Add(mainController.pServerClientController.Instance.Id); } else if (mainController.pTUNTAPController != null) { processList.Add(mainController.pTUNTAPController.Instance.Id); } else if (mainController.pNFController != null) { processList.Add(mainController.pNFController.Instance.Id); } Logging.Info("启动流量统计 PID:" + string.Join(",", processList.ToArray())); Task.Run(() => { using (var session = new TraceEventSession("KernelAndClrEventsSession")) { session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP); //这玩意儿上传和下载得到的data是一样的:) //所以暂时没办法区分上传下载流量 session.Source.Kernel.TcpIpRecv += data => { if (processList.Contains(data.ProcessID)) { lock (counterLock) received += data.size; //Logging.Info($"TcpIpRecv: {Compute(data.size)}"); } }; session.Source.Kernel.UdpIpRecv += data => { if (processList.Contains(data.ProcessID)) { lock (counterLock) received += data.size; //Logging.Info($"UdpIpRecv: {Compute(data.size)}"); } }; session.Source.Process(); } }); if ((Convert.ToInt32(MainForm.Instance.LastDownloadBandwidth) - Convert.ToInt32(received)) == 0) { MainForm.Instance.OnBandwidthUpdated(0); received = 0; } while (MainForm.Instance.State != State.Stopped) { Task.Delay(1000).Wait(); lock (counterLock) { MainForm.Instance.OnBandwidthUpdated(Convert.ToInt64(received)); } } } } }