1

我想在我的 C# 应用程序中按进程测量带宽网络。

我试图在 Process Object 中找到此信息,但是,此信息不存在。

我也尝试过使用性能计数器,但我没有按进程找到带宽信息。

您是否知道按进程在 Windows XP 到 Windows 8 上的应用程序工作测量网络带宽(发送的网络字节,接收的网络字节)?

我知道Windows有这个信息,因为当我们打开“资源监视器”时,我可以在网络选项卡中选择一个特定的应用程序,我们可以实时看到发送和接收的字节数。

谢谢。

4

2 回答 2

5

据我所知,你不能用纯 C# 来做到这一点,你必须对 IP Helper 库进行一些 P/Invoke 调用。

因为这涉及到很多,所以我将简要概述您需要进行的 API 调用。

首先,这在 Windows XP 上不起作用,因为某些 API 是新的(这就是该版本不存在资源监视器的原因)。如果您需要 Windows XP 支持,恐怕您将不得不使用 WinPCap 之类的东西。在 Vista+ 上,我们可以进行更新的网络信息调用,情况会变得更好。

对 IPv4、IPv6、TCP 和 UDP 有单独的调用。为简洁起见,我将仅概述 IPv4/TCP 集,因为一旦您了解了该过程,就可以轻松复制它以填充其他部分。

要开始,您需要调用GetTcpTable2(). 这将为您提供机器上当前活动的连接表。你最终会MIB_TCPTABLE2得到一堆MIB_TCPROW2结构。每个结构代表一个连接。

MIB_TCPROW2结构有一个 PID 字段,您可以将其与当前进程 ID 匹配。

这意味着不断轮询连接表,对其进行迭代并转储与您的进程相关的行。

对于这些行中的每一行,您必须调用GetPerTcpConnectionEStats(). 您会感兴趣两种统计类型,第一种TcpConnectionEstatsData返回有关发送和接收的字节数的信息。第二个TcpConnectionEstatsBandwidth返回有关连接带宽的信息。

我没有为此显示任何代码的原因是它非常复杂并且涉及大量结构编组,但希望我给你的内容比你目前拥有的更多。

以下是这些功能的 MSDN 链接:

GetTcpTable2()- http://msdn.microsoft.com/en-us/library/bb408406(v=vs.85).aspx GetPerTcpConnectionEStats() - http://msdn.microsoft.com/en-us/library/bb485738(v=vs. 85).aspx

于 2013-01-25T14:06:41.577 回答
2

GetTcpTable2()C# 中的一个简单示例。

[DllImport("iphlpapi.dll", SetLastError = true)]
static extern int GetTcpTable2(byte[] pTcpTable, out int pdwSize, bool bOrder);

static void Main(string[] args) {
  int pdwSize = 20000;
  byte[] buffer = new byte[pdwSize];
  int res = GetTcpTable2(buffer, out pdwSize, true);
  if (res != 0) {
    buffer = new byte[pdwSize];
    res = GetTcpTable2(buffer, out pdwSize, true);
    if (res != 0) throw new Exception(res);
  }

  int nOffset = 0;
  var dwNumEntries = Convert.ToInt32(buffer[nOffset]); nOffset += 4;
  Console.WriteLine("total connection: {0}", dwNumEntries);

  for (int i = 0; i < dwNumEntries; i++) {
    Console.WriteLine("*****************");
    int st = Convert.ToInt32(buffer[nOffset]);
    Console.WriteLine("state: {0}", st); nOffset += 4;

    string LocalAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." 
      + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString();
    Console.WriteLine("local ip: {0}", LocalAdrr); nOffset += 4;

    int LocalPort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) +
      (((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16);
    Console.WriteLine("local port: {0}", LocalPort); nOffset += 4;

    string RemoteAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." 
      + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString();
    Console.WriteLine("remote ip: {0}", RemoteAdrr); nOffset += 4;

    int RemotePort = (RemoteAdrr == "0.0.0.0") ? 0
      : RemotePort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) +
        (((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16);
    Console.WriteLine("remote port: {0}", RemotePort); nOffset += 4;

    int pid = BitConverter.ToInt32(buffer.Skip(nOffset).Take(4).ToArray(), 0);
    Console.WriteLine("pid: {0}", pid); nOffset += 4;

    int OffloadState = Convert.ToInt32(buffer[nOffset]);
    Console.WriteLine("OffloadState: {0}", OffloadState); nOffset += 4;
  }

}
于 2013-11-21T09:03:34.480 回答