当前位置:首页 > Windows程序 > 正文

windows下使用C#获取特定进程网络流量

2021-03-26 Windows程序

最近老板接了一个中船重工的项目,需要做一个有关海军软件系统的组件评估项目,项目中有一个子项目需要获取特定进程的各种系统参数,项目使用.NET平台。在获取特定进程各种系统参数时,其它诸如进程ID,进程名,进程私有工作集,,进程工作集,进程IO吞吐量,进程CPU占用率等都可以直接使用.NET中的相关API直接获取,例如使用PerformanceCounter对象可以获取进程私有工作集、进程工作集、进程IO吞吐量等,但是对于特定进程的网络上行流量和下行流量却没有办法直接使用.NET中API获取,网上也找了很多资料,了解到只能通过对特定进程使用的端口号进行抓包来获取进程网络流量,具体实现时自己也想过使用C#调用winpcap库,但由于实现比较复杂,所以就放弃了使用该方法。后来在网上找到了一个国外使用C#实现的winpcap库SharpPcap库,于是使用SharpPcap库实现了获取特定进程网络流量功能。准备工作是需要将SharpPcap库下载到计算机,然后再项目中引用PacketDotNet.dll和SharpPcap.dll,然后添加引用:

using SharpPcap; using PacketDotNet;

具体实现比较复杂,以下介绍一下实现中的核心部分:

首先定义ProcessPerformanceInfo类,用来记录进程相关信息,ProcessPerformanceInfo定义如下

//记录特定进程性能信息的类 public class ProcessPerformanceInfo : IDisposable { public int ProcessID { get; set; }//进程ID public string ProcessName { get; set; }//进程名 public float PrivateWorkingSet { get; set; }//私有工作集(KB) public float WorkingSet { get; set; }//工作集(KB) public float CpuTime { get; set; }//CPU占用率(%) public float IOOtherBytes { get; set; }//每秒IO操作(不包含控制操作)读写数据的字节数(KB) public int IOOtherOperations { get; set; }//每秒IO操作数(不包括读写)(个数) public long NetSendBytes { get; set; }//网络发送数据字节数 public long NetRecvBytes { get; set; }//网络接收数据字节数 public long NetTotalBytes { get; set; }//网络数据总字节数 public List<ICaptureDevice> dev = new List<ICaptureDevice>(); /// <summary> /// 实现IDisposable的方法 /// </summary> public void Dispose() { foreach (ICaptureDevice d in dev) { d.StopCapture(); d.Close(); } } }

定义一个ProcessPerformanceInfo类型的属性ProcInfo:

public ProcessPerformanceInfo ProcInfo { get; set; }

第一步:获取指定进程使用的所有端口号

由于一个进程可能使用多个端口号,因此监视一个进程流量时必须监视该进程使用的所有端口号,具体可以通过cmd执行命令netstat -ano并对结果进行分析。代码如下:

//进程id int pid = ProcInfo.ProcessID; //存放进程使用的端口号链表 List<int> ports = new List<int>(); #region 获取指定进程对应端口号 Process pro = new Process(); pro.StartInfo.FileName = "cmd.exe"; pro.StartInfo.UseShellExecute = false; pro.StartInfo.RedirectStandardInput = true; pro.StartInfo.RedirectStandardOutput = true; pro.StartInfo.RedirectStandardError = true; pro.StartInfo.CreateNoWindow = true; pro.Start(); pro.StandardInput.WriteLine("netstat -ano"); pro.StandardInput.WriteLine("exit"); Regex reg = new Regex("\\s+", RegexOptions.Compiled); string line = null; ports.Clear(); while ((line = pro.StandardOutput.ReadLine()) != null) { line = line.Trim(); if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase)) { line = reg.Replace(line, ","); string[] arr = line.Split(,); if (arr[4] == pid.ToString()) { string soc = arr[1]; int pos = soc.LastIndexOf(:); int pot = int.Parse(soc.Substring(pos + 1)); ports.Add(pot); } } else if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase)) { line = reg.Replace(line, ","); string[] arr = line.Split(,); if (arr[3] == pid.ToString()) { string soc = arr[1]; int pos = soc.LastIndexOf(:); int pot = int.Parse(soc.Substring(pos + 1)); ports.Add(pot); } } } pro.Close(); #endregion

所获取的端口号都存放在ports里。

第二步:获取本机IP地址和本机网络设备(即网卡)

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/67604.html