【问题标题】:Getting Received and Sent Bytes generated by Process for Network Activity获取网络活动进程生成的接收和发送字节
【发布时间】:2019-09-17 16:47:39
【问题描述】:

这是我之前的question 的下一步。


我正在创建一个 C# WinForm 应用程序,它将显示给定进程(例如:进程名称的 chrome.exe)的网络活动(接收的字节数/发送的字节数)和进程生成的速度(以兆比特/秒为单位)。

在使用性能计数器 IO Read Bytes/secIO Read Bytes/sec 时,会显示 I/O 读取和写入字节,而不是 “发送和接收字节”

PS:I/O 计算进程生成的所有文件、网络和设备 I/O 字节。但是,我只想要特定进程生成的网络字节。

我只想检索 Bytes Received 和 Bytes Sent。但是,不知道使用什么计数器来获取进程的这些字节。

我已经为此目的搜索了这些链接,但没有用:

这是尝试过的 Process 的性能计数器代码:

PerformanceCounter bytesReceived = new PerformanceCounter("Process", "IO Read Bytes/sec");
PerformanceCounter bytesSent = new PerformanceCounter("Process", "IO Write Bytes/sec");
string ProcessName = "chrome";
bytesReceived.InstanceName = ProcessName;
bytesSent.InstanceName = ProcessName;

问题:我如何才能获取网络活动的进程生成的接收和发送字节数。

【问题讨论】:

  • 我想要使用PerformanceCounter的解决方案。
  • 在仔细阅读了您提供的链接和this one 之后,我很确定PerformanceCounter 类是不可能的,因为它仅从一组或多或少预定义的受限集合中提取计数器。在我的本地系统上列出可用的计数器表明没有机会在不包括磁盘 I/O 的情况下定位某个进程。
  • @JanWichelmann 你的意思是PerformanceCounter 不可能吗?如果是,那么我如何才能实现它。

标签: c# .net process performancecounter


【解决方案1】:

正如 cmets 中已经提到的,我认为没有办法使用 PerformanceCounter 类来实现这一点。由于它使用 Windows 的内置性能计数器,因此可以通过使用 typeperf 命令查询已安装计数器的整个列表来验证这一点。在我的本地机器上,这产生了大约 3200 个不同的计数器,我通过这些计数器来验证我的声明。实际上有are 用于网络发送/接收的计数器(即使对于特定的网络接口/适配器或处理器),但它们都不能过滤特定的进程或进程系列。


因此,更简单的方法可能是使用this(已经非常完整)的答案,它使用了Microsoft.Diagnostics.Tracing.TraceEvent NuGet 包。为了进行测试,我将其压缩为最少量的代码并对其进行了修改以捕获整个进程系列的流量。

static void Main(string[] args)
{
    // Counter variables
    var counterLock = new object();
    int received = 0;
    int sent = 0;

    // Fetch ID of all Firefox processes
    var processList = Process.GetProcessesByName("firefox").Select(p => p.Id).ToHashSet();

    // Run in another thread, since this will be a blocking operation (see below)
    Task.Run(() =>
    {
        // Start ETW session
        using(var session = new TraceEventSession("MyKernelAndClrEventsSession"))
        {
            // Query network events
            session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);

            // Subscribe to trace events
            // These will be called by another thread, so locking is needed here
            session.Source.Kernel.TcpIpRecv += data =>
            {
                if(processList.Contains(data.ProcessID))
                    lock(counterLock)
                        received += data.size;
            };
            session.Source.Kernel.TcpIpSend += data =>
            {
                if(processList.Contains(data.ProcessID))
                    lock(counterLock)
                        sent += data.size;
            };

            // Process all events (this will block)
            session.Source.Process();
        }
    });

    // Program logic to handle counter values
    while(true)
    {
        // Wait some time and print current counter status
        Task.Delay(2000).Wait();
        lock(counterLock)
            Console.WriteLine($"Sent: {sent.ToString("N0")} bytes    Received: {received.ToString("N0")} bytes");
    }
}

请注意,您需要提升(管理员)权限才能执行此代码。

我使用 Mozilla Firefox 进行了测试,当时它运行了 10 个进程(7 个选项卡);我下载了一个大文件,程序正确打印了添加的网络流量(加上来自活动选项卡的一些噪音),不包括涉及的磁盘访问(这至少会使测量的流量增加一倍)。

另请注意,这仅捕获 TCP/IP 流量;要同时捕获 UDP/IP 流量,您需要订阅 UdpIpSendUdpIpRecv 事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    相关资源
    最近更新 更多