【问题标题】:determining the current link speed of WiFi in C#在 C# 中确定 WiFi 的当前链接速度
【发布时间】:2013-07-07 21:26:21
【问题描述】:

我正在编写一个程序,它只做一件事,它会找出 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);

在main方法中。

【问题讨论】:

    标签: c# wifi wireless


    【解决方案1】:

    考虑到我花了一整天的时间才找到解决这个问题的方法,我想我至少应该向 StackOverflow 展示一下我遇到了什么以及做了什么和做了什么没有 解决这个问题。

    tl;dr: 滚动到代码部分

    我发现了什么

    不错的控制面板

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

    WMI

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

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

    WMI,简而言之,就是一个巨大的对象数据库(即 也可以通过 SQL 查询),它允许您查询有关一个 Windows机器如进程、磁盘等。在WMI中,一切都是 由具有一系列 实例class 表示,每个实例都有一组 属性
    不管怎样,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 structure 解决了这个问题。如果您查看 MSDN 页面,它是一个相当大的结构,但这里重要的是 TransmitLinkSpeed,它确实有效

    调用GetAdaptersAddresses() function 将返回实际结构。

    现在,实际的 C# P/Invoke 代码。幸运的是,pinvoke.net already had interop 我添加了这个功能。这就是所有必要的。

    代码

    最后,您的代码使用新的 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),可能有一些 "leaky abstractions" (.Net),或者使用起来很痛苦 (Win32)。

    叹息,说了这么多,希望对你有帮助。

    【讨论】:

    • 我不是在尝试确定互联网速度,而是在尝试确定 802.11n 连接的链接速度。这些将是诸如 28、56、72、96、116、124、130、148、156、162、192、216、232、240、270 或 300 之类的数字。这是我什至无需连接到互联网。这是可以通过网络发送的理论最大带宽,而不是实际最大带宽。
    • 非常感谢您。我已经有了控制面板方法,以及另一种特定于 Windows 8 的方法,但这些方法都不符合我的需要。你的代码正是我要找的,所以非常感谢。
    • 有人在 uwp 上测试过这个吗?
    【解决方案2】:

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

    select Description , DeviceID, Speed from CIM_NetworkAdapter
    

    得到:

    D-Link DWA-140 RangeBooster N USB Adapter    17    285000000
    

    【讨论】:

      【解决方案3】:

      既然这里还没有人提到它:为什么不使用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。

      【讨论】:

        猜你喜欢
        • 2016-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-03
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        相关资源
        最近更新 更多