4

我正在编写一个程序,它只做一件事,它会找出 wifi 连接的当前链接速度并将其实时报告给用户。我遇到的问题是它似乎无法找出当前的链接速度,只能找出设备的最大链接速度(300 Mbps)。我写这篇文章的原因是我有一个问题,链接速度会周期性地急剧下降(下降到 1-2 Mbps),我希望能够看到这种情况何时发生。使用此代码,它只会给我适配器支持的最大速度,而不是连接的当前链接速度。

private void update(object state)
{

    System.Net.NetworkInformation.NetworkInterface[] nics = null;
    nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
    long speed = 0;
    string adapter = "";
    foreach (System.Net.NetworkInformation.NetworkInterface net in nics)
    {
        if (net.Name.Contains("Wireless") || net.Name.Contains("WiFi") || net.Name.Contains("802.11") || net.Name.Contains("Wi-Fi"))
        {
            speed = net.Speed;
            adapter = net.Name;
            break;
        }
    }
    string temp;
    if (speed == 0)
    {
        temp = "There is currently no Wi-Fi connection";
    }
    else
    {
        temp = "Current Wi-Fi Speed: " + (speed / 1000000) + "Mbps on " + adapter;
    }
    if (label1.InvokeRequired)
    {
        SetTextCallback d = new SetTextCallback(update);
        label1.Invoke(d, new object[] { temp });
    }
    else
    {
        label1.Text = temp;
    }
}

这通过调用运行

System.Threading.Timer ticker = new System.Threading.Timer(update, label1, 0, 1000);

在主要方法中。

4

3 回答 3

15

考虑到我花了一整天的时间才找到解决方案,我想我至少会展示 StackOverflow 以供将来参考,我遇到了什么,什么对这个问题有效,什么无效。

tl;dr: 滚动到代码部分

我发现了什么

不错的控制面板

如果您正在寻找真正简单的方法来执行此操作,您只需打开控制面板即可。根据您使用的 Windows 版本(在我的情况下,我使用的是 Windows 8),页面的路径是控制面板 >> 网络和 Internet >> 网络和共享中心,然后您可以单击旁边的链接“Connections:”这将为您提供一个如下所示的窗口。Wi-Fi 信息窗口
当前的链接速度以红色突出显示,在我的例子中是 36.0 Mbps。当然,如果您打算将一些代码与实际值集成,这可能无法满足您最初的问题。

WMI

结合谷歌搜索和诸如此类的东西,我想我可能在Windows Management Instrumentation中找到了一些东西。

长话短说,AFAIK,WMI没有我们正在寻找的东西。

简而言之, WMI是一个巨大的对象数据库(也可以通过 SQL 查询),它允许您查询有关 Windows 机器的信息,例如进程、磁盘等。在 WMI 中,一切都由一个包含一系列每个实例都有一组 属性
无论如何,WMI Explorer允许您在您的机器上查看所有这些。

我(据说)在 MSDN 上找到了两个类,它们可能包含有关链接速度的信息,但从 WMI Explorer 中,没有任何用处。

第一个类,MSFT_NetAdapter甚至没有出现在我机器上的 WMI Explorer 中。

第二个类Win32_NetworkAdapter显示在 WMI Explorer 中,但Speed属性仍然不正确。同一个网络适配器显示的值为168000000或 168 Mbps,这是不正确的。虽然我觉得这很奇怪,因为已经有一个MaxSpeed但它是空白的。

将 WMI 从列表中划掉。

Win32 P/调用

是的,当然,所有问题的解决方案总是使用P/Invoke魔法调用非托管 Win32 API。

这是用来解决问题的路线

幸运的是,IP_ADAPTER_ADDRESSES 结构解决了这个问题。如果您查看 MSDN 页面,它是一个相当大的结构,但这里重要的是TransmitLinkSpeed确实有效

调用该GetAdaptersAddresses()函数将返回实际结构。

现在,实际的 C# P/Invoke 代码。幸运的是,pinvoke.net 已经为我添加的这个功能提供了互操作性。这就是所有必要的。

编码

最后,这是用新的 P/Invoke 黑魔法修补的代码。我已将其作为控制台应用程序用于演示目的:

使用语句:

using System;
using System.Threading;

代码:

class Program
{
    private static void Main(string[] args)
    {
        Timer ticker = new Timer(Update, null, 0, 1000);

        // Keep the main thread from dying
        while (true)
        {
            Thread.Sleep(1000);
        }
    }

    private static void Update(object state)
    {
        ulong speed = 0;
        string adapter = "";

        string[] nameSearches = { "Wireless", "WiFi", "802.11", "Wi-Fi" };

        // The enum value of `AF_INET` will select only IPv4 adapters.
        // You can change this to `AF_INET6` for IPv6 likewise
        // And `AF_UNSPEC` for either one
        foreach (IPIntertop.IP_ADAPTER_ADDRESSES net in IPIntertop.GetIPAdapters(IPIntertop.FAMILY.AF_INET))
        {
            bool containsName = false;
            foreach (string name in nameSearches)
            {
                if (net.FriendlyName.Contains(name))
                {
                    containsName = true;
                }
            }
            if (!containsName) continue;

            speed = net.TrasmitLinkSpeed;
            adapter = net.FriendlyName;
            break;
        }
        
        string temp;
        if (speed == 0)
        {
            temp = "There is currently no Wi-Fi connection";
        }
        else
        {
            temp = string.Format("Current Wi-Fi Speed: {0} Mbps on {1}", (speed / 1000000.0), adapter);
        }
        
        Console.WriteLine(temp);
    }
}

然后,您将寻找IPIntertop我更新的实际课程。由于它很大,您可以在pinvoke.net或此PasteBin上找到它的更新,以防出现问题。

底线

Windows 有很多API 有点损坏(WMI),可能有一些“泄漏的抽象”(.Net),或者使用起来很痛苦(Win32)。

叹息,这很多,我希望它有所帮助。

于 2013-07-07T21:42:54.010 回答
1

我遇到了同样的问题,需要获得当前协商的 Windows wifi 链接速度。并且感谢@Jaxrtech 的 WMI 方法,它确实有效。正确的类是 CIM_NetworkAdapter(我使用的是 windows7),并查询速度列以获取当前速度。虽然 wifi 当前协商速度正在改变,但这个速度也在改变。我测试了它,这匹配确定。

select Description , DeviceID, Speed from CIM_NetworkAdapter

得到:

D-Link DWA-140 RangeBooster N USB Adapter    17    285000000
于 2013-07-23T08:52:55.303 回答
0

由于这里还没有人提到它:为什么不使用https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface.speed?view=net-5.0#System_Net_NetworkInformation_NetworkInterface_Speed

也就是说,如果此站点上的表格自 .NET Framework 2.0 起是正确包含的,并且似乎包含在所有其他版本的 .net 中,包括 .net core。

于 2021-06-30T13:22:14.617 回答