基於 Qt 的 NTP Client 實現

2021-08-30 14:21:58 字數 2321 閱讀 7954

ntp,network timestamp protocol,網路時間協議。

ntp client 簡單來說,就是以網路上某個節點上的時間為基準,校正本機時間。

ntp server 即提供本機時間戳給 client 校準的伺服器。

ntp 協議是基於 udp 的。

ntp 的實現是 c/s 結構的,client 向 server 傳送時間校準請求,server 返回校準後時間。

既然是網路訪問,那必然會有網路延時問題,這就必然導致 server 返回的時間戳不准。

如何解決呢?

我們來分別看一下 client 和 server 的時間線:

server --------------------------------------------  ts

t2 t3

t1 t4

client -------------------------------------------- tc

如上圖,定義:

下面,我們來計算 t。

根據以上的變數,我們可得出如下方程組:

t2 = t1 + d + t。 即,t2 的數值,是 t1 加上網路延時 d、再加上 ts 、tc之間的誤差 t

t4 = t3 +d + (-t)。即,t4 的數值,是 t3 加上網路延時 d、再加上 tc、ts 之間的誤差 -t

其中, t1、t2、t3、t4 都是確定的數值,即可解出方程租:

t2 - t4 = t1 + t - t3 - (-t)
變換後可得如下算式:

t = ((t2 - t1) + (t3 - t4) ) /2
這樣,有了 ts 和 tc 之間的時間戳誤差,client 就可以調整了:

ntp報文格式如上圖所示,它的字段含義參考如下:

li 閏秒標識器,占用2個bit。0 即可。

vn 版本號,占用3個bits,表示ntp的版本號,現在為3

mode 模式,占用3個bits,表示模式。 3 表示 client, 2 表示 server

stratum(層),占用8個bits。不清楚怎麼用

poll 測試間隔,占用8個bits,表示連續資訊之間的最大間隔。不清楚怎麼用

precision 精度,占用8個bits,,表示本地時鐘精度。 不清楚怎麼用

root delay根時延,占用8個bits,表示在主參考源之間往返的總共時延。 不清楚怎麼用

root dispersion根離散,占用8個bits,表示在主參考源有關的名義錯誤。 不清楚怎麼用

reference identifier參考時鐘識別符號,占用8個bits,用來標識特殊的參考源。不同的 ntp server 改字段不一樣

參考時間戳,64bits時間戳,本地時鐘被修改的最新時間。一般由 server 端填寫,表示 server 上次同步時間戳的時間點

原始時間戳,客戶端傳送的時間,64bits。即公式中的 t1 。client 請求時必須填寫,server 端響應時、回寫請求包裡的該字段

接受時間戳,服務端接受到的時間,64bits。即公式中的 t2 。server 端填寫

傳送時間戳,服務端送出應答的時間,64bits。即公式中的 t3。server 端填寫

認證符(可選項)

注意:t4 為client 收到響應的時間戳,只有收到了才會產生,因此 t4 不體現在協議報文裡。

網路延時 d,計算時假定了請求和響應的延時相等,但真實網路環境非常複雜,udp 本身可靠度也不夠高,可能請求包很快就到伺服器、而響應包在網路上饒了一大圈才到,這就會產生誤差。

這種誤差很難徹底消除,但還是有一些手段可以減少誤差。

以前做物理實驗,測量物體的長度、重量等,一般要求測量多次,最後取平均值。

本實現裡思路也是發起多次 ntp 請求,最後取平均誤差。

但考慮到計算機的計算環境,略有優化:

取 10 個不同地域的共有 ntp server,分別獲取時間戳誤差

ntp 請求成功數少於 3 個 認為 失敗

ntp 請求成功數大於等於 3 個 且 小於 8 個,則求和計算平均誤差

ntp 請求成功數等於 8 個時,按位計算平均誤差

ntp 請求成功數等於 9 個時,去掉乙個最大值後,按位計算平均誤差

ntp 請求成功數等於 10 個時,去掉乙個最大值、去掉乙個最小值後,按位計算平均誤差

基於Redis的BloomFilter實戰

離線資料處理與實時資料處理有很大的不同,其中乙個例子就是去重。在聚資料中,訪問uv和購買uv都需要實時的去重。離線處理的時候,我們可以通過count groupby 或者count distinct 等方式比較容易的計算出uv,而且不用太擔心效能,大不了就是多一點map或者執行時間久一點。那麼在實時...

基於C 的Qt(四)

介面設計時使用最多的元件恐怕就是qlabel和qlineedit,qlabel用於顯示字串,qlineedit用於顯示和輸入字串。這兩個函式都涉及qstring類。qstring類是qt程式裡經常使用的類,用於處理字串。qstring類可以進行字串與數字之間的轉換,使用qlineedit就可以實現數...

基於Qt的時鐘設計

時鐘本身使用paintevent函式進行繪製,使用timerevent進行定時重新整理。繪製時鐘,通過paintevent實現,包括 時鐘背景,表盤,刻度線,數字以及時針,分針,秒針。使用timerevent定時重新整理,設定重新整理時間為1000毫秒 1秒 void dialog painteve...