尤良芳,董 忠
(天水師范學(xué)院 物理與信息科學(xué)學(xué)院,甘肅 天水 741001)
隨著網(wǎng)絡(luò)的發(fā)展,局域網(wǎng)、物聯(lián)網(wǎng)廣泛應(yīng)用于各行各業(yè),使用的服務(wù)器、工作站及各類智能終端都有自己的時鐘,且都可以調(diào)節(jié),但無法保證網(wǎng)絡(luò)中所有設(shè)備與主機(jī)時間的同步。經(jīng)過長期運行,時間差會越來越大,但在網(wǎng)絡(luò)環(huán)境下的應(yīng)用中可能會引發(fā)意想不到的問題。如在分布式計算環(huán)境中,由于每個主機(jī)時間不一致,會造成同一操作在不同主機(jī)的記錄時間不一致,將導(dǎo)致服務(wù)無法正常地進(jìn)行。保證網(wǎng)內(nèi)服務(wù)器和工作站或其它嵌入式設(shè)備之間時間的同步已成為非常重要的問題。[1]
開源軟件OpenNTPD 采用SNTP/NTP 網(wǎng)絡(luò)時間協(xié)議,用于把本地時鐘與一個或多個遠(yuǎn)程NTP服務(wù)器進(jìn)行時間同步,既可以作為客戶端使用,也可以設(shè)置成為NTP服務(wù)器為其他機(jī)器提供時間服務(wù);作為OpenBSD操作系統(tǒng)的一個子項目,OpenNTPD設(shè)計目標(biāo)是:用一個簡單、安全、方便管理的方式精確計算機(jī)的時鐘;它是OpenBSD 操作系統(tǒng)缺省的時間同步管理軟件。
OpenNTPD 代碼結(jié)構(gòu)清晰、簡單小巧,占用內(nèi)存少;和其他時間服務(wù)器軟件相比,如ntp.org 提供的網(wǎng)絡(luò)時間協(xié)議(RFC1305,RFC2030)應(yīng)用程序ntp-4.2.6p5.tar.gz 大小為4M,而openNTPD-3.9p1.tar.gz僅為150k。[2-3]
OpenNTPD 雖然廣泛應(yīng)用于互聯(lián)網(wǎng),但在自成體系、封閉(無外聯(lián))的局域網(wǎng)絡(luò)環(huán)境中,作為網(wǎng)絡(luò)時間服務(wù)器應(yīng)用時,卻無法為網(wǎng)內(nèi)其它設(shè)備提供時間服務(wù)。如圖1,NTP 服務(wù)器ip 地址為192.168.56.101,安裝OpenNTPD3.9p1 為網(wǎng)內(nèi)客戶機(jī)提供時間服務(wù)。客戶機(jī)使用ntpd與NTP服務(wù)器同步時,出現(xiàn)以下兩類錯誤提示:如圖2 和圖3,本文旨在從SNTPv4 協(xié)議和目前最新的OpenNTPD3.9p1 源代碼入手分析該問題存在的原因,并提出對其源代碼的改進(jìn)。
圖1 OpenNTPD時間服務(wù)器局域網(wǎng)應(yīng)用示意圖
圖2 局域網(wǎng)應(yīng)用時錯誤提示1
圖3 局域網(wǎng)應(yīng)用時錯誤提示2
NTP協(xié)議(the Network Time Protocol version 3,由RFC 1305 描述)是網(wǎng)絡(luò)時間協(xié)議的簡稱,廣泛用于互聯(lián)網(wǎng)上進(jìn)行計算機(jī)時鐘同步,通過該協(xié)議與國際標(biāo)準(zhǔn)時間同步。NTP根據(jù)上級同步源和網(wǎng)絡(luò)路徑的不同,能夠提供1-50ms的時間精確度。
NTP協(xié)議精度高,算法復(fù)雜。在實際很多應(yīng)用中,秒級的精確度就足夠了,SNTP 協(xié)議(Simple Network Time Protocol version 4,由RFC 2030 描述)通過簡化NTP 訪問協(xié)議,在保證秒級時間精確度的前提下,使得對網(wǎng)絡(luò)時間同步的開發(fā)和應(yīng)用變得容易。SNTP協(xié)議目前的版本號是SNTP V4,主要對NTP 協(xié)議涉及有關(guān)訪問安全、服務(wù)器自動遷移部分進(jìn)行了縮減。SNTP采用與NTP 格式一樣的數(shù)據(jù)包,計算客戶時間、時間偏差以及包往返時延的算法也是一樣的,所以SNTP 與NTP 協(xié)議具有互操作性,即SNTP 客戶可以與NTP 服務(wù)器協(xié)同工作,同樣NTP 客戶也可以接收SNTP 服務(wù)器發(fā)出的授時信息。[4]
SNTP 消息一般封裝在UDP 協(xié)議包中,它利用UDP的123端口提供服務(wù)。SNTP信息幀格式如圖4描述:
協(xié)議中主要的數(shù)據(jù)項說明如下。
LI:當(dāng)前時間閏秒標(biāo)志。字段長度為2bit,只在服務(wù)器端有效。其值定義為:
0:無警告;1:最后一分鐘是61秒;2:最后一分鐘是59 秒;3:警告(時鐘沒有同步);服務(wù)器在開始時,LI設(shè)置為3,一旦與主機(jī)時鐘取得同步后就設(shè)置成其它值。
VN:協(xié)議版本號。字段長度為3bit,當(dāng)前協(xié)議版本號為4。
Mode:指示協(xié)議模式。字段長度為3bit,其值定義為:
0:保留;1:對稱主動;2:對稱被動;3:客戶;4:服務(wù)器;5:廣播;6:保留為NTP 控制信息;7:保留為用戶定義;
在單播和多播模式,客戶在請求時把這個字段設(shè)置為3,服務(wù)器在響應(yīng)時把這個字段設(shè)置為4。在廣播模式下,服務(wù)器把這個字段設(shè)置為5。
Stratum:指示服務(wù)器工作的級別;
該字段只在服務(wù)器端有效,字段長度為8bit。其值定義為:
0:故障信息(kiss-o'-death message);1:一級服務(wù)器;2-15:二級服務(wù)器;16-255:保留;
圖4 SNTPv4協(xié)議格式
NTP服務(wù)器與上級時間源取得同步后,才能為客戶機(jī)提供準(zhǔn)確的時間服務(wù)。NTP協(xié)議按照離外部NTP 源的遠(yuǎn)近將所有服務(wù)器歸入不同的Stratum(層)中。Stratum-1 為頂層,Stratum-15 為最低層,Stratum層的總數(shù)限制在15以內(nèi)。
Precision:系統(tǒng)時鐘的精確性,字段長度為8bit 符號整數(shù),以秒為單位,作為2 的指數(shù)方的指數(shù)部分,取值范圍從-6到-20。該字段只在服務(wù)器端有效。
Root Delay:指示與主時鐘參考源的往返延遲,字段長度為32bit,以秒為單位,該字段只在服務(wù)器端有效。
Root Dispersion:與主時鐘參考源的誤差,字段長度為32bit,以秒為單位,該字段只在服務(wù)器端有效。
Reference Identifier:時鐘參考源的標(biāo)記。對于一級服務(wù)器,字段長度為4 字節(jié)ASCII 字符串,左對齊不足添零。對于二級服務(wù)器,在IPV4 環(huán)境下,取值為一級服務(wù)器的IP 地址。該字段只在服務(wù)器端有效
Reference Timestamp:系統(tǒng)時鐘最后一次校準(zhǔn)的時間,64bit 時間戳格式表示。該字段只在服務(wù)器端有效,
Originate Timestamp:客戶向服務(wù)器發(fā)起請求的時間,以前面所述64bit時間戳格式表示。
Transmit Timestamp:服務(wù)器向客戶發(fā)時間戳的時間,以前面所述64bit時間戳格式表示。[5]
以SNTPv4 工作模式中最常用的單播模式,來說明服務(wù)器的工作過程:
openNTPD 服務(wù)器在初始化時,主函數(shù)ntp_main()調(diào)用函數(shù)setup_listeners()在123 端口建立UDP 服務(wù);函數(shù)server_dispatch()將數(shù)據(jù)包結(jié)構(gòu)體ntp_msg 成員status中LI字段設(shè)置為3(表示未與上級服務(wù)器同步);VN 字段設(shè)置為4,表示SNTPv4;Mode 字段設(shè)置為4(服務(wù)器模式);成員stratum和ppoll 設(shè)置為0;成員precision 設(shè)置為0xFA(十進(jìn)制為-6)。
SNTP 服務(wù)器在工作過程中,如果與外部時鐘源失去同步,Stratum字段設(shè)置為0,此時客戶收到這個信息時,會丟棄服務(wù)器發(fā)給它的時間戳信息。
一旦服務(wù)器與外部時鐘源取得同步后,進(jìn)入工作狀態(tài),在日志中會記錄“clock is now synced”。LI字段設(shè)置為0,stratum字段設(shè)置為外部時鐘源服務(wù)器的stratum+1;Reference Identifier 字段設(shè)置為時鐘源的ip 地址,如十六進(jìn)制C0 A8 FE 01 表示192.168.254.1,Precision 字段和前邊設(shè)置相同,即為0xFA(十進(jìn)制為-6);VN 字段設(shè)置為客戶端請求信息包的VN 字段值,Root Delay 和Root Dispersion 字段設(shè)置為0,Reference Timestamp 字段設(shè)置為從外部時鐘源最新取得的時間,Originate Timestamp 字段設(shè)置為客戶請求包的Transmit Timestamp 字段值,Transmit Timestamp 字段設(shè)置為服務(wù)器發(fā)出時間戳給客戶的時間。
ntpd.c 處理命令行參數(shù)及相關(guān)函數(shù)的調(diào)用;
ntp.c 包含處理進(jìn)程之間通訊相關(guān)函數(shù);
client.c包含NTP協(xié)議及算法相關(guān)的函數(shù),作為客戶機(jī)與上級NTP服務(wù)器保持時間同步;
server.c 為客戶機(jī)提供NTP時間服務(wù);
ntp_msg.c 協(xié)議包發(fā)送和接收;
ntp_dns.c 域名解析;
log.c 日志記錄;
在文件ntp.h中SNTPv4(RFC2030)協(xié)議包定義如下:
函數(shù)client_dispatch()首先調(diào)用ntp_getmsg()從上一級NTP 時間服務(wù)器獲得協(xié)議數(shù)據(jù)包,將其存于struct ntp_msg 結(jié)構(gòu)變量msg中,并與268行開始對結(jié)構(gòu)成員status和stratum判斷,其關(guān)鍵代碼如下:
282 行函數(shù)log_info()日志記錄時間未同步的原因,字符串s 為錯誤提示信息,273 行和276 行的strlcpy()函數(shù)分別給出了圖2 和圖3 的錯誤提示信息;由相對應(yīng)的if 語句可知,圖2 中錯誤原因是客戶端接收的協(xié)議包中成員status 中LI 字段為0,即服務(wù)器未與其上級時間服務(wù)器同步;圖3錯誤原因是客戶端接收的協(xié)議包中成員stratum為0,即服務(wù)器失去與其上級時間服務(wù)器同步。在局域網(wǎng)(未外聯(lián))中該時間服務(wù)器由于沒有上級時間服務(wù)器,所以出現(xiàn)圖2 和圖3 中的錯誤提示,并停止服務(wù),該分析與2.2中SNTPv4協(xié)議簡介相互印證。
server.c文件中函數(shù)server_dispatch()構(gòu)造發(fā)送給客戶的協(xié)議數(shù)據(jù)包,其關(guān)鍵代碼如下:
其中變量status為ntp_status結(jié)構(gòu),用于保存服務(wù)器的的狀態(tài)參量,該結(jié)構(gòu)在htpd.h中定義如下:
其中103 行synced成員保存服務(wù)器是否已與外接時間同步源同步,成員stratum 保存服務(wù)器級別,在封閉的局域網(wǎng)內(nèi),其值均為零;應(yīng)在160行和169行對其代碼進(jìn)行改造,改造后的關(guān)鍵代碼如下:
即設(shè)服務(wù)器已與外接時間服務(wù)器同步,其級別為3級。
將修改后的代碼進(jìn)行編譯運行,客戶端不再有錯誤提示,并能夠保持和服務(wù)器的時間同步,在實際測試中效果良好。修改后的OpenNTPD代碼,既保持了原代碼的優(yōu)良特性,又?jǐn)U展了其應(yīng)用的范圍。
[1]于承先.集約化水產(chǎn)養(yǎng)殖信息系統(tǒng)的設(shè)計與實現(xiàn)[J].農(nóng)業(yè)工程學(xué)報,2008,2(24):235-238.
[2]OpenNTPD[EB/OL].http://www.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/ntpd/,2012-04-10.
[3]OpenBSD Manual[EB/OL].http://www.openbsd.org/cgi-bin/man.cgi,2012-04-10.
[4]RFC1305.Network Time Protocol(Version 3)Specification,Implementation and Analysis[EB/OL].http://www.faqs.org/rfcs/rfc1305.html,2012-04-10.
[5]RFC2030.Simple Network Time Protocol (SNTP) Version 4 for IPv4,IPv6 and OSI[EB/OL].Ihttp://www.faqs.org/rfcs/rfc2030.html,2012-04-10.