[C#] 利用NetworkInformation取得目前連線中的上傳與下載速率

利用NetworkInformation可找到一些相關網路的資訊,包括了bytesReceived、bytesSent、Packets等等資訊,當得到了bytesReceived與bytesSent參數時,便能計算出上傳與下載的速率,並配合ManagedWIfi取得目前連線狀態,達到自動取得目前連線中的上傳下載速率的功能。

using System.Net.NetworkInformation; //取得IPv4資訊需加入
using NativeWifi;                    //取得目前連線狀況需加入

需加入以上兩個參考,已供本程式使用相關參數,其中NativeWifi需額外安裝 ManagedWifi.dll才能加入,其安裝方法為在"套件管理器主控台" 輸入install-package managedwifi即可。

完整CODE如下:

namespace speedtest
{
    class Program
    {
        static int count = 0;         //speedInit()需使用到
        static long bytesRX = 0;      //儲存bytesReceived
        static long bytesTX = 0;      //儲存bytesSent
        static NetworkInterface[] netInterfaceAry; //建立netInterfaceAry by NetworkInterface[]

        static void Main(string[] args)
        {
            speedInit();
            spdtimer();
            Console.ReadLine();
        }


        static private void speedInit()           //此方法為自動取得正在連線中網路介面
        {
             netInterfaceAry = NetworkInterface.GetAllNetworkInterfaces();
            WlanClient wlanClient = new WlanClient();
                        
            foreach (NetworkInterface netInterface in netInterfaceAry)
            {
                if (netInterface.Name == wlanClient.Interfaces[0].InterfaceName)
                {
                    break;
                }
                count++;
            }
        }

        static private void speedFunction(object obj,System.Timers.ElapsedEventArgs e)  //為上傳與下載速率的方法
        {
            IPv4InterfaceStatistics ipv4stat = netInterfaceAry[count].GetIPv4Statistics();

            double download = (double)(ipv4stat.BytesReceived - bytesRX) / 1024;
            int upload = (int)(ipv4stat.BytesSent - bytesTX) / 1024;

            bytesRX = ipv4stat.BytesReceived;
            bytesTX = ipv4stat.BytesSent;
            Console.Clear();
            Console.WriteLine("網路介面卡名稱:"+netInterfaceAry[count].Name );
            Console.WriteLine("下載速度:" + download+" KB/s");
            Console.WriteLine("上傳速度:" + upload+" KB/s");
            Console.WriteLine("已接收bytes:" + bytesRX);
            Console.WriteLine("已傳送bytes:" + bytesTX);

        }

        static private void spdtimer()  //timer初始化,每秒執行一次speedFimction()
        {
            System.Timers.Timer spdTimer = new System.Timers.Timer(1000);
            spdTimer.Elapsed += new System.Timers.ElapsedEventHandler(speedFunction);
            spdTimer.Enabled = true;
            spdTimer.AutoReset = true;
            spdTimer.Start();
        }
           
    }
}

以下將個別針對speedInit()、speedFunction()、spdtimer()分析。

speedInit()

        static private void speedInit()           //此方法為自動取得正在連線中網路介面
        {
             netInterfaceAry = NetworkInterface.GetAllNetworkInterfaces();
            WlanClient wlanClient = new WlanClient();
                        
            foreach (NetworkInterface netInterface in netInterfaceAry)
            {
                if (netInterface.Name == wlanClient.Interfaces[0].InterfaceName)
                {
                    break;
                }
                count++;
            }
        }

在此方法中,建立一個netInterfaceAry,該屬性為NetworkInterface[] 陣列類別,並使用NetworkInterface.GetAllNetworkInterfaces();取得所有網卡介面資訊。

在本範例使用的電腦中,就顯示了[0]~[8] 9個網路介面卡資料項,而這邊指的網路介面卡資訊可從裝置管理員中的網路介面卡項目找到各界面名稱

其中本裝置正在連線的項目為[4],如下圖所示,使用網卡為AC3160,名稱為"Wi-Fi",但要如何讓程式在這9個項目中選出真正在連線狀態的介面呢? 

使用ManagedWifi中的WlanClient便能得到目前連線的狀態囉!

new 一個 wlanClient用來取得目前裝置上連線中的狀態,WlanClient wlanClient = new WlanClient();

可以看到目前連線中的介面名稱為InterfaceName="Wi-Fi"

            foreach (NetworkInterface netInterface in netInterfaceAry)
            {
                if (netInterface.Name == wlanClient.Interfaces[0].InterfaceName)
                {
                    break;
                }
                count++;
            }

接著使用foreach將netInterfaceAry陣列個別解析到 netInterface,並使用if判斷目前陣列元素的netInterface.Name是否等於wlanClient.Interfaces[0].InterfaceName,如果否count++,並繼續讀取陣列的下一個元素,直到if為true為止,並利用break終止foreach,便得到目前正在連線的Interface Array在第幾項了。

 

 speedFunction()

        static private void speedFunction(object obj,System.Timers.ElapsedEventArgs e)  //為上傳與下載速率的方法
        {
            IPv4InterfaceStatistics ipv4stat = netInterfaceAry[count].GetIPv4Statistics();

            int download = (int)(ipv4stat.BytesReceived - bytesRX) / 1024;
            int upload = (int)(ipv4stat.BytesSent - bytesTX) / 1024;

            bytesRX = ipv4stat.BytesReceived;
            bytesTX = ipv4stat.BytesSent;
            Console.Clear();
            Console.WriteLine("網路介面卡名稱:"+netInterfaceAry[count].Name );
            Console.WriteLine("下載速度:" + download+" KB/s");
            Console.WriteLine("上傳速度:" + upload+" KB/s");
            Console.WriteLine("已接收bytes:" + bytesRX);
            Console.WriteLine("已傳送bytes:" + bytesTX);

        }

speedFunction為讀取bytesReceived與bytesSent並計算下載與上傳速率的Function,該Function每秒將被Timer調用一次,因此該變量參數為(object obj,System.Timers.ElapsedEventArgs e)。

計算下載與上傳速率所使用到的兩個參數為 bytesReceived與bytesSent,可在IPv4InterfaceStatistics中找到,因此建立一個ipv4stat,其使用的介面為netInterfaceAry[count],其中count在speedInit已得到,便ㄑ為正在連線中的Interface。

其下載速率的計算方式=這次的接收到的bytes數(bytesReceived) - 前一秒接收到的bytes數(bytesReceived) /1024 便能得到 XX KB/s

接著每次再將bytesReceived存到bytesRX中以供下一次使用。最後在Console.Write 打印出上下載速率。

 

 spdtimer()

   static private void spdtimer()  //timer初始化,每秒執行一次speedFimction()
        {
            System.Timers.Timer spdTimer = new System.Timers.Timer(1000); //1000毫秒執行一次
            spdTimer.Elapsed += new System.Timers.ElapsedEventHandler(speedFunction); //每秒執行speedFunction
            spdTimer.Enabled = true; //Timer始能
            spdTimer.AutoReset = true;  //重複計數
            spdTimer.Start();//Timer開始
        }

建立一個Timer,每秒執行一次 speedFunction(),此例中使用的Timer為System.Timers.Timer,

        static void Main(string[] args)
        {
            speedInit();
            spdtimer();
            Console.ReadLine();
        }

 接著再Main中順序調用speedInit()、spdtimer()。