Rust 實現 NTP 客戶端 - 1
本文是用 Rust 創建簡單 NTP 客戶端系列文章的第一部分,我們將介紹協議本身,然後構建一個與 NTP 服務器通信的基本應用程序。
NTP 允許網絡中的計算機將它們的本地系統時間與 NTP 服務器上的某個時間點對齊。
我們需要設置請求的 header 來獲得服務器的 response,NTP 服務器將告訴我們時間,這個時間對於大多數應用程序來說足夠準確。
我們向 NTP Server 發送一個 48 字節長的包,第一個字節設置爲 0x1b,response 是相同的包結構,我們可以從偏移量 40 的位置讀取一個 32 位的字來獲得傳輸時間。
讓我們創建一個新的項目:
cargo new ntp_part1
編輯 Cargol.toml 文件添加 byteorder 依賴:
[dependencies]
byteorder = "1"
在 main.rs 中引入相關模塊:
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Cursor, Seek, SeekFrom};
use std::net::UdpSocket;
然後在 main 函數中,我們寫入基本的客戶端代碼:
fn main() {
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut transmit: Vec<u8> = vec![0; 48];
transmit[0] = 0x1b;
let _bytes_transmitted = socket.send_to(&transmit, "pool.ntp.org:123").unwrap();
let mut buf = [0; 48];
let _bytes_received = socket.recv(&mut buf).unwrap();
let ntp_time = process_ntp_packet(&buf);
let unix_time: u64 = ntp_time - 2208988800;
dbg!(&unix_time);
}
這個過程遵循大多數 POSIX 系統常見的傳統 UDP 套接字創建和傳輸 / 接收範式。
在第 2 行創建套接字,我們將其綁定到端口 0 以允許操作系統定義發送端口。第 6 行發送報文,第 9 行接收報文。
收到響應後,調用 process_ntp_packet 函數:
fn process_ntp_packet(buffer: &[u8]) -> u64 {
let mut reader = Cursor::new(buffer);
reader.seek(SeekFrom::Start(40)).unwrap();
let transmit_timestamp_seconds = reader.read_u32::<BigEndian>().unwrap();
u64::from(transmit_timestamp_seconds)
}
運行 cargo run:
master:ntp_part1 Justin$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
Running `target/debug/ntp_part1`
[src/main.rs:18] &unix_time = 1657641335
在下一部分,我們將添加一些錯誤處理和單元測試。
本文翻譯自:
https://medium.com/towardsdev/rust-foo-ntp-client-part-1-6bc4c8cce720
coding 到燈火闌珊 專注於技術分享,包括 Rust、Golang、分佈式架構、雲原生等。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/YDKIDS0NVHs6pGgN9qEW_Q