NetFlowService.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. //************************************************************************
  2. // https://github.com/yuzhengyang
  3. // author: yuzhengyang
  4. // date: 2016.5.1 - 2017.6.12
  5. // desc: 网络流量监测工具
  6. // Copyright (c) yuzhengyang. All rights reserved.
  7. //************************************************************************
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Linq;
  12. using System.Net;
  13. using Y.Utils.AppUtils;
  14. using Y.Utils.DataUtils.Collections;
  15. using Y.Utils.NetUtils.NetInfoUtils;
  16. using Y.Utils.WindowsUtils.ProcessUtils;
  17. using static Y.Utils.NetUtils.NetInfoUtils.NetProcessTool;
  18. namespace Y.Utils.NetUtils.NetManUtils
  19. {
  20. public class NetFlowService
  21. {
  22. public bool IsNetFlowRun { get { return _IsNetFlowRun; } }
  23. private bool _IsNetFlowRun = false;
  24. public bool IsNetPacketRun { get { return _IsNetPacketRun; } }
  25. private bool _IsNetPacketRun = false;
  26. public List<NetProcessInfo> NetProcessInfoList = new List<NetProcessInfo>();
  27. public NetFlowTool NetFlow = new NetFlowTool();
  28. List<NetPacketTool> NetPacketList = new List<NetPacketTool>();
  29. NetProcessTool.TcpRow[] TcpConnection;
  30. NetProcessTool.UdpRow[] UdpConnection;
  31. Process[] NowProcess;
  32. List<string> AllIPv4Address = new List<string>();
  33. public long LostPacketCount { get; set; }
  34. /// <summary>
  35. /// 开启网络流量监控
  36. /// </summary>
  37. public void Start()
  38. {
  39. #region 启动系统性能计数器统计
  40. try
  41. {
  42. NetFlow.Start();
  43. NetFlow.DataMonitorEvent += DataMonitorEvent;
  44. _IsNetFlowRun = true;
  45. }
  46. catch { }
  47. #endregion
  48. #region 启动Socket包统计
  49. if (PermissionTool.IsAdmin())
  50. {
  51. List<IPAddress> hosts = NetCardInfoTool.GetIPv4Address();
  52. AllIPv4Address = NetCardInfoTool.GetAllIPv4Address();
  53. foreach (var host in hosts)
  54. {
  55. try
  56. {
  57. NetPacketTool p = new NetPacketTool(host);
  58. p.NewPacket += new NewPacketEventHandler(NewPacketEvent);
  59. p.Start();
  60. NetPacketList.Add(p);
  61. }
  62. catch { }
  63. }
  64. if (ListTool.HasElements(NetPacketList)) _IsNetPacketRun = true;
  65. }
  66. #endregion
  67. }
  68. /// <summary>
  69. /// 关闭网络流量监控
  70. /// </summary>
  71. public void Stop()
  72. {
  73. if (_IsNetFlowRun)
  74. {
  75. NetFlow.Stop();
  76. _IsNetFlowRun = false;
  77. }
  78. if (_IsNetPacketRun)
  79. {
  80. NetPacketList.ForEach(x => { x.Stop(); });
  81. _IsNetPacketRun = false;
  82. }
  83. }
  84. /// <summary>
  85. /// 系统性能计数器每秒统计事件
  86. /// </summary>
  87. /// <param name="n"></param>
  88. public void DataMonitorEvent(NetFlowTool n)
  89. {
  90. NowProcess = Process.GetProcesses();
  91. GetConnection();
  92. SetNetProcess();
  93. CalcNetProcessInfo();
  94. CheckRestart();
  95. }
  96. /// <summary>
  97. /// 整理数据包到所属的进程
  98. /// </summary>
  99. /// <param name="tool"></param>
  100. /// <param name="packet"></param>
  101. private void NewPacketEvent(NetPacketTool tool, Packet packet)
  102. {
  103. bool isGather = false;
  104. #region 整理TCP包
  105. if (packet.Protocol == Protocol.Tcp && ListTool.HasElements(TcpConnection) && ListTool.HasElements(NowProcess))
  106. {
  107. lock (TcpConnection)
  108. {
  109. // tcp 下载
  110. if (TcpConnection.Any(x => x.RemoteIP.ToString() == packet.DestinationAddress.ToString() && x.RemotePort == packet.DestinationPort))
  111. {
  112. var tcpDownload = TcpConnection.FirstOrDefault(x => x.RemoteIP.ToString() == packet.DestinationAddress.ToString() && x.RemotePort == packet.DestinationPort);
  113. var process = NowProcess.FirstOrDefault(x => x.Id == tcpDownload.ProcessId);
  114. if (process != null)
  115. {
  116. var info = NetProcessInfoList.FirstOrDefault(x => x.ProcessName == process.ProcessName);
  117. if (info != null)
  118. {
  119. isGather = true;
  120. info.DownloadBag += packet.TotalLength;
  121. info.DownloadBagCount += packet.TotalLength;
  122. }
  123. }
  124. }
  125. // tcp 上传
  126. if (TcpConnection.Any(x => x.LocalIP.ToString() == packet.SourceAddress.ToString() && x.LocalPort == packet.SourcePort))
  127. {
  128. var tcUpload = TcpConnection.FirstOrDefault(x => x.LocalIP.ToString() == packet.SourceAddress.ToString() && x.LocalPort == packet.SourcePort);
  129. var process = NowProcess.FirstOrDefault(x => x.Id == tcUpload.ProcessId);
  130. if (process != null)
  131. {
  132. var info = NetProcessInfoList.FirstOrDefault(x => x.ProcessName == process.ProcessName);
  133. if (info != null)
  134. {
  135. isGather = true;
  136. info.UploadBag += packet.TotalLength;
  137. info.UploadBagCount += packet.TotalLength;
  138. }
  139. }
  140. }
  141. }
  142. }
  143. #endregion
  144. #region 整理UDP包
  145. if (packet.Protocol == Protocol.Udp && ListTool.HasElements(UdpConnection) && ListTool.HasElements(NowProcess))
  146. {
  147. lock (UdpConnection)
  148. {
  149. // tcp 下载
  150. if (UdpConnection.Any(x => x.LocalPort == packet.DestinationPort) && AllIPv4Address.Contains(packet.DestinationAddress.ToString()))
  151. {
  152. var udpDownload = UdpConnection.FirstOrDefault(x => AllIPv4Address.Contains(x.LocalIP.ToString()) && x.LocalPort == packet.DestinationPort);
  153. var process = NowProcess.FirstOrDefault(x => x.Id == udpDownload.ProcessId);
  154. if (process != null)
  155. {
  156. var info = NetProcessInfoList.FirstOrDefault(x => x.ProcessName == process.ProcessName);
  157. if (info != null)
  158. {
  159. isGather = true;
  160. info.DownloadBag += packet.TotalLength;
  161. info.DownloadBagCount += packet.TotalLength;
  162. if (info.ProcessName == "Idle")
  163. {
  164. }
  165. }
  166. }
  167. }
  168. // udp 上传
  169. if (UdpConnection.Any(x => x.LocalPort == packet.SourcePort) && AllIPv4Address.Contains(packet.SourceAddress.ToString()))
  170. {
  171. var udpIp = AllIPv4Address.FirstOrDefault(x => x == packet.SourceAddress.ToString());
  172. var ucUpload = UdpConnection.FirstOrDefault(x => AllIPv4Address.Contains(x.LocalIP.ToString()) && x.LocalPort == packet.SourcePort);
  173. var process = NowProcess.FirstOrDefault(x => x.Id == ucUpload.ProcessId);
  174. if (process != null)
  175. {
  176. var info = NetProcessInfoList.FirstOrDefault(x => x.ProcessName == process.ProcessName);
  177. if (info != null)
  178. {
  179. isGather = true;
  180. info.UploadBag += packet.TotalLength;
  181. info.UploadBagCount += packet.TotalLength;
  182. if (info.ProcessName == "Idle")
  183. {
  184. }
  185. }
  186. }
  187. }
  188. }
  189. }
  190. #endregion
  191. if (!isGather)
  192. {
  193. LostPacketCount++;
  194. }
  195. }
  196. #region 获取所有网络连接
  197. /// <summary>
  198. /// 获取所有网络连接并整理列表
  199. /// </summary>
  200. void GetConnection()
  201. {
  202. TcpConnection = NetProcessTool.GetTcpConnection();
  203. UdpConnection = NetProcessTool.GetUdpConnection();
  204. }
  205. #endregion
  206. #region 设置程序流量及连接数统计列表
  207. /// <summary>
  208. /// 清空并重置当前所有程序的连接数
  209. /// </summary>
  210. void SetNetProcess()
  211. {
  212. // 清空已有连接数
  213. if (ListTool.HasElements(NetProcessInfoList))
  214. NetProcessInfoList.ForEach(x =>
  215. {
  216. x.NetConnectionInfoList = new List<NetConnectionInfo>();
  217. });
  218. // 统计TCP连接数
  219. if (ListTool.HasElements(TcpConnection))
  220. {
  221. foreach (var t in TcpConnection)
  222. {
  223. SetNetProcessConnection(t);
  224. }
  225. }
  226. // 统计UDP连接数
  227. if (ListTool.HasElements(UdpConnection))
  228. {
  229. foreach (var u in UdpConnection)
  230. {
  231. SetNetProcessConnection(u);
  232. }
  233. }
  234. }
  235. /// <summary>
  236. /// 整理TCP连接到所属的进程
  237. /// </summary>
  238. /// <param name="t"></param>
  239. void SetNetProcessConnection(TcpRow t)
  240. {
  241. try
  242. {
  243. Process p = NowProcess.FirstOrDefault(x => x.Id == t.ProcessId);
  244. if (p != null)
  245. {
  246. var ppl = NetProcessInfoList.FirstOrDefault(x => x.ProcessName == p.ProcessName);
  247. if (ppl == null)
  248. {
  249. NetProcessInfoList.Add(
  250. new NetProcessInfo()
  251. {
  252. ProcessId = p.Id,
  253. ProcessIcon = ProcessInfoTool.GetIcon(p, false),
  254. ProcessName = p.ProcessName,
  255. LastUpdateTime = DateTime.Now,
  256. NetConnectionInfoList = new List<NetConnectionInfo>() {
  257. new NetConnectionInfo() {
  258. LocalIP = t.LocalIP.ToString(),
  259. LocalPort = t.LocalPort,
  260. RemoteIP = t.RemoteIP.ToString(),
  261. RemotePort = t.RemotePort,
  262. ProtocolName = "TCP",
  263. Status = t.State,
  264. LastUpdateTime = DateTime.Now,
  265. }
  266. },
  267. });
  268. }
  269. else
  270. {
  271. ppl.LastUpdateTime = DateTime.Now;
  272. var conn = ppl.NetConnectionInfoList.FirstOrDefault(x => x.LocalIP == t.LocalIP.ToString() && x.LocalPort == t.LocalPort && x.RemoteIP == t.RemoteIP.ToString() && x.RemotePort == t.RemotePort);
  273. if (conn == null)
  274. {
  275. ppl.NetConnectionInfoList.Add(new NetConnectionInfo()
  276. {
  277. LocalIP = t.LocalIP.ToString(),
  278. LocalPort = t.LocalPort,
  279. RemoteIP = t.RemoteIP.ToString(),
  280. RemotePort = t.RemotePort,
  281. ProtocolName = "TCP",
  282. Status = t.State,
  283. LastUpdateTime = DateTime.Now,
  284. });
  285. }
  286. }
  287. }
  288. }
  289. catch (Exception e)
  290. { }
  291. }
  292. /// <summary>
  293. /// 整理UDP连接到所属的进程
  294. /// </summary>
  295. /// <param name="u"></param>
  296. void SetNetProcessConnection(UdpRow u)
  297. {
  298. try
  299. {
  300. Process p = NowProcess.FirstOrDefault(x => x.Id == u.ProcessId);
  301. if (p != null)
  302. {
  303. var ppl = NetProcessInfoList.FirstOrDefault(x => x.ProcessName == p.ProcessName);
  304. if (ppl == null)
  305. {
  306. NetProcessInfoList.Add(
  307. new NetProcessInfo()
  308. {
  309. ProcessId = p.Id,
  310. ProcessIcon = ProcessInfoTool.GetIcon(p, false),
  311. ProcessName = p.ProcessName,
  312. LastUpdateTime = DateTime.Now,
  313. NetConnectionInfoList = new List<NetConnectionInfo>() {
  314. new NetConnectionInfo() {
  315. LocalIP = u.LocalIP.ToString(),
  316. LocalPort = u.LocalPort,
  317. ProtocolName = "UDP",
  318. LastUpdateTime = DateTime.Now,
  319. }
  320. },
  321. });
  322. }
  323. else
  324. {
  325. ppl.LastUpdateTime = DateTime.Now;
  326. var conn = ppl.NetConnectionInfoList.FirstOrDefault(x => x.LocalIP == u.LocalIP.ToString() && x.LocalPort == u.LocalPort);
  327. if (conn == null)
  328. {
  329. ppl.NetConnectionInfoList.Add(new NetConnectionInfo()
  330. {
  331. LocalIP = u.LocalIP.ToString(),
  332. LocalPort = u.LocalPort,
  333. ProtocolName = "UDP",
  334. LastUpdateTime = DateTime.Now,
  335. });
  336. }
  337. }
  338. }
  339. }
  340. catch (Exception e)
  341. { }
  342. }
  343. #endregion
  344. #region 整理程序流量汇总信息
  345. /// <summary>
  346. /// 整理计算程序网络流量
  347. /// </summary>
  348. void CalcNetProcessInfo()
  349. {
  350. if (ListTool.HasElements(NetProcessInfoList))
  351. {
  352. NetProcessInfoList.ForEach(p =>
  353. {
  354. p.UploadDataCount += p.UploadData;
  355. p.DownloadDataCount += p.DownloadData;
  356. });
  357. int allupbag = NetProcessInfoList.Sum(x => x.UploadBag);
  358. int alldownbag = NetProcessInfoList.Sum(x => x.DownloadBag);
  359. NetProcessInfoList.ForEach(p =>
  360. {
  361. if (allupbag > 0 && NetFlow.UploadData > 0)
  362. {
  363. float uprate = (float)p.UploadBag / allupbag;
  364. p.UploadData = (int)(uprate * NetFlow.UploadData);
  365. }
  366. if (alldownbag > 0 && NetFlow.DownloadData > 0)
  367. {
  368. float downrate = (float)p.DownloadBag / alldownbag;
  369. p.DownloadData = (int)(downrate * NetFlow.DownloadData);
  370. }
  371. p.UploadBag = 0;
  372. p.DownloadBag = 0;
  373. p.LastUpdateTime = DateTime.Now;
  374. });
  375. }
  376. }
  377. #endregion
  378. #region 联网断网重启计划
  379. /// <summary>
  380. /// 联网断网重启计划(应对断网或重连后网卡抓包报错造成的不准确)
  381. /// </summary>
  382. private void CheckRestart()
  383. {
  384. bool rest = false;
  385. string[] ints = NetCardInfoTool.GetInstanceNames();
  386. if (ListTool.IsNullOrEmpty(NetFlow.Instances) && ListTool.HasElements(ints))
  387. {
  388. rest = true;
  389. }
  390. if (ListTool.HasElements(NetFlow.Instances) && ListTool.HasElements(ints) &&
  391. string.Join("-", NetFlow.Instances) != string.Join("-", ints))
  392. {
  393. rest = true;
  394. }
  395. if (rest)
  396. {
  397. //重启 系统性能计数器
  398. NetFlow.Restart();
  399. //重启 抓包监听
  400. List<IPAddress> hosts = NetCardInfoTool.GetIPv4Address();
  401. AllIPv4Address = NetCardInfoTool.GetAllIPv4Address();
  402. foreach (var host in hosts)
  403. {
  404. try
  405. {
  406. if (!NetPacketList.Any(x => x.IP.ToString() == host.ToString()))
  407. {
  408. NetPacketTool p = new NetPacketTool(host);
  409. p.NewPacket += new NewPacketEventHandler(NewPacketEvent);
  410. p.Start();
  411. NetPacketList.Add(p);
  412. }
  413. }
  414. catch { }
  415. }
  416. }
  417. }
  418. #endregion
  419. }
  420. }