用 Rust 實作網路測速小工具

#rust
用 Rust 實作網路測速小工具
五倍技術部
技術文章
用 Rust 實作網路測速小工具

網路已經是現代生活不可或缺的一部分,但是當我們需要通過網路來獲取或傳送資料時,網路的速度就顯得非常重要。那麼要如何準確地知道我們的網路速度是多少呢?通常我們會選擇使用一些線上的網路測速工具,或者我們可以自己實作一個本地的網路測速工具。

Rust 是一個提供記憶體安全、並發和高效能的系統程式設計語言,它非常適合用於實作這類的系統工具。在這篇文章中,我們將透過 Rust 語言,從零開始實作一個簡單的網路測速小工具。透過這個小工具,我們可以輕鬆地在本地環境中測試我們的網路下載速度,以後就不用再使用線上的網路測速工具了。

安裝套件

首先在專案中安裝 reqwesttokio 套件,reqwest 會處理 HTTP Client 的部分,tokio 則是處理非同步執行。

[dependencies]
reqwest = "0.11.20"
tokio = { version = "1.32.0", features = ["full"] }

網路測速的原理

網路測速的原理,會透過下載一個檔案,並且計算下載的速度,其實就是計算下載的資料量除以下載的時間,就可以得到下載的速度,計算公式如下:

下載速度 = 下載的資料量 / 下載的時間

如果是下載一個 200 MB 的檔案,並且下載的時間是 10 秒,那麼下載的速度就是 20 MB/s。

但是這個速度跟我們平常看到的網路速度不太一樣,因為我們平常看到的網路速度是指的資料傳輸的速度,而不是下載的速度,所以我們需要將下載的速度換算成資料傳輸的速度,換算公式如下:

資料傳輸速度 = 下載的速度 * 8

如果是下載一個 200 MB 的檔案,並且下載的時間是 10 秒,那麼下載的速度就是 20 MB/s,資料傳輸的速度就是 160 Mbps。

如何實作

知道原理是透過下載一個檔案來測試網路的下載速度,我們就可以實際來做看看。

會使用 reqwest::get() 來發送 HTTP 請求,並且使用 response.bytes() 來取得下載的資料,最後計算下載的速度。

use reqwest;
use std::time::Instant;

#[tokio::main]
async fn main() {
    let url = "http://http.speed.hinet.net/test_200m.zip";

    println!("開始測試下載速度...");

    let start_time = Instant::now();

    match reqwest::get(url).await {
        Ok(response) => {
            if !response.status().is_success() {
                println!("測試下載時發生錯誤: {:?}", response.status());
                return;
            }

            match response.bytes().await {
                Ok(bytes) => {
                    let duration = start_time.elapsed();
                    let speed_in_mbps =
                        (bytes.len() * 8) as f64 / duration.as_secs_f64() / 1_000_000.0;
                    println!("網路下載速度: {:.2} Mbps", speed_in_mbps);
                    println!("下載完成,耗時: {:.2} 秒", duration.as_secs_f64());
                }
                Err(e) => {
                    println!("讀取下載資料時發生錯誤: {:?}", e);
                }
            }
        }
        Err(e) => {
            println!("下載時發生錯誤: {:?}", e);
        }
    }
}

這裡並不會下載檔案到你的電腦中,而是會將檔案下載到記憶體中,所以不用擔心會佔用到你的硬碟空間。不過如果選擇下載的檔案太大,可能會導致記憶體不足,所以要注意一下。

這邊選擇下載的檔案是 200 MB 的檔案,可以參考中華電信提供的測試檔案。
HTTP 檔案傳輸測試

接下來在終端機執行 cargo run,就可以看到測試的結果。

Bonus

現在測試的過程中,只會顯示一串文字「開始測試下載速度…」,感覺有點無聊,所以來加入一點動態的效果。

    let loading_dots_task = task::spawn(async {
        let mut count = 0;
        loop {
            sleep(Duration::from_secs(1)).await;
            count += 1;
            if count <= 3 {
                print!(".");
            } else {
                // 重置計數器並移動游標回到起始位置,再次開始 print
                count = 0;
                print!("\r開始測試下載速度 ");
            }
            // 強制立即輸出不緩存
            std::io::stdout().flush().unwrap();
        }
    });

這一段程式碼會在背景執行,每隔一秒鐘就會顯示一個點,並且在顯示三個點之後,就會清除畫面,並且再次顯示「開始測試下載速度」。

最後要加上一段 code,終止 task 的執行。

loading_dots_task.abort();

最後看一下執行的結果:

執行結果

總結

透過實作這個小工具,我們可以看到 Rust 語言在系統程式設計方面的強大能力,它不僅能讓我們輕鬆地實作出高效且安全的系統工具,也提供了豐富的生態圈支持,讓我們能快速地完成開發任務,期待在未來能夠在更多的領域中看到 Rust 語言的身影。

📚 五倍學院全新線上直播課程 | 為你自己學 Rust 🦀
帶你認識 Rust 語言的核心概念,從資料型態、變數與常數、函數和閉包,帶你全面掌握 Rust 獨特使用性,用更安全又高效的方式處理記憶體,打造更好的應用程式
✅日期:1/15 (一) & 1/17 (三)
✅時間:19:00 - 22:00
✅立即報名:https://5xcamp.us/AfgkdR
✅原價 NT 1,450 元,限時優惠價 NT 999 元 !