c# - 检索进程网络使用情况

标签 c# .net networking network-programming performancecounter

我怎样才能让进程发送/接收字节?首选方法是使用 C#。

我已经搜索了很多,但没有找到任何简单的解决方案。一些解决方案建议在机器上安装 WinPCap 并使用此库。

就像这个人问的:Need "Processes with Network Activity" functionality in managed code - Like resmon.exe does it 我不想要 lib 的开销。

有没有简单的解决方案? 实际上,我想要 Windows 资源监视器在“具有网络事件的进程”选项卡下提供的确切数据:enter image description here

Windows 的资源监视器是如何获取这些信息的? 有什么例子吗?

此外,尝试使用此处提到的计数器方法: Missing network sent/received 但没有成功——因为不是每个进程都显示在这个柜台下。 我再次想知道资源监视器如何在不使用此计数器的情况下获取此信息...

最佳答案

资源监视器使用ETW - 值得庆幸的是,微软创造了一个很好的 nuget .net wrapper使其更易于使用。

我最近写了这样的东西来报告我进程的网络 IO:

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;

namespace ProcessMonitoring
{
    public sealed class NetworkPerformanceReporter : IDisposable
    {
        private DateTime m_EtwStartTime;
        private TraceEventSession m_EtwSession;

        private readonly Counters m_Counters = new Counters();

        private class Counters
        {
            public long Received;
            public long Sent;
        }

        private NetworkPerformanceReporter() { }

        public static NetworkPerformanceReporter Create()
        {
            var networkPerformancePresenter = new NetworkPerformanceReporter();
            networkPerformancePresenter.Initialise();
            return networkPerformancePresenter;
        }

        private void Initialise()
        {
            // Note that the ETW class blocks processing messages, so should be run on a different thread if you want the application to remain responsive.
            Task.Run(() => StartEtwSession()); 
        }

        private void StartEtwSession()
        {
            try
            {
                var processId = Process.GetCurrentProcess().Id;
                ResetCounters();

                using (m_EtwSession = new TraceEventSession("MyKernelAndClrEventsSession"))
                {
                    m_EtwSession.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);

                    m_EtwSession.Source.Kernel.TcpIpRecv += data =>
                    {
                        if (data.ProcessID == processId)
                        {
                            lock (m_Counters)
                            {
                                m_Counters.Received += data.size;
                            }
                        }
                    };

                    m_EtwSession.Source.Kernel.TcpIpSend += data =>
                    {
                        if (data.ProcessID == processId)
                        {
                            lock (m_Counters)
                            {
                                m_Counters.Sent += data.size;
                            }
                        }
                    };

                    m_EtwSession.Source.Process();
                }
            }
            catch
            {
                ResetCounters(); // Stop reporting figures
                // Probably should log the exception
            }
        }

        public NetworkPerformanceData GetNetworkPerformanceData()
        {
            var timeDifferenceInSeconds = (DateTime.Now - m_EtwStartTime).TotalSeconds;

            NetworkPerformanceData networkData;

            lock (m_Counters)
            {
                networkData = new NetworkPerformanceData
                {
                    BytesReceived = Convert.ToInt64(m_Counters.Received / timeDifferenceInSeconds),
                    BytesSent = Convert.ToInt64(m_Counters.Sent / timeDifferenceInSeconds)
                };

            }

            // Reset the counters to get a fresh reading for next time this is called.
            ResetCounters();

            return networkData;
        }

        private void ResetCounters()
        {
            lock (m_Counters)
            {
                m_Counters.Sent = 0;
                m_Counters.Received = 0;
            }
            m_EtwStartTime = DateTime.Now;
        }

        public void Dispose()
        {
            m_EtwSession?.Dispose();
        }
    }

    public sealed class NetworkPerformanceData
    {
        public long BytesReceived { get; set; }
        public long BytesSent { get; set; }
    }
}

关于c# - 检索进程网络使用情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17026204/

相关文章:

C# 字典计算组值的总和

delphi - 如何使用Delphi枚举所有可用的WiFi网络

c# - OpenXml SpreadsheetDocument.Open(...) 出现异常 - 缺少主要部分

c# - 如何阻止 ASP.NET Web API 隐式解释 HTTP 方法?

.NET 自定义属性属性?

linux - netstat 如何确定符号主机名?

networking - Haskell:如何使用 forkIO 使多个客户端连接到服务器?

c# - 内部并在私有(private) api 中受到保护

c# - 统一。哪个更快 : one big script with switch(ObjectType) or lot of simple scripts?

c# - 更改图像源属性时崩溃