通过NTP协议进行时间同步
NTP(Network Time Protocol,網絡時間協議)是由RFC 1305定義的時間同步協議,用來在分布式時間服務器和客戶端之間進行時間同步。NTP基于UDP報文進行傳輸,使用的UDP端口號為123。
使用NTP的目的是對網絡內所有具有時鐘的設備進行時鐘同步,使網絡內所有設備的時鐘保持一致,從而使設備能夠提供基于統一時間的多種應用。
對于運行NTP的本地系統,既可以接收來自其他時鐘源的同步,又可以作為時鐘源同步其他的時鐘,并且可以和其他設備互相同步。
NTP工作原理
NTP的基本工作原理如圖所示。Device A和Device B通過網絡相連,它們都有自己獨立的系統時鐘,需要通過NTP實現各自系統時鐘的自動同步。為便于理解,作如下假設:
在Device A和Device B的系統時鐘同步之前,Device A的時鐘設定為10:00:00am,Device B的時鐘設定為11:00:00am。
?Device B作為NTP時間服務器,即Device A將使自己的時鐘與Device B的時鐘同步。
?? NTP報文在Device A和Device B之間單向傳輸所需要的時間為1秒。
?????? 系統時鐘同步的工作過程如下:
?? Device A發送一個NTP報文給Device B,該報文帶有它離開Device A時的時間戳,該時間戳為10:00:00am(T1)。
? 當此NTP報文到達Device B時,Device B加上自己的時間戳,該時間戳為11:00:01am(T2)。
? 當此NTP報文離開Device B時,Device B再加上自己的時間戳,該時間戳為11:00:02am(T3)。
? 當Device A接收到該響應報文時,Device A的本地時間為10:00:03am(T4)。
至此,Device A已經擁有足夠的信息來計算兩個重要的參數:
?NTP報文的往返時延Delay=(T4-T1)-(T3-T2)=2秒。
? Device A相對Device B的時間差offset=((T2-T1)+(T3-T4))/2=1小時。
這樣,Device A就能夠根據這些信息來設定自己的時鐘,使之與Device B的時鐘同步。
NTP的報文格式
NTP有兩種不同類型的報文,一種是時鐘同步報文,另一種是控制報文。控制報文僅用于需要網絡管理的場合,它對于時鐘同步功能來說并不是必需的,這里不做介紹。
?
主要字段的解釋如下:
l????????????? LI(Leap Indicator):長度為2比特,值為“11”時表示告警狀態,時鐘未被同步。為其他值時NTP本身不做處理。
l????????????? VN(Version Number):長度為3比特,表示NTP的版本號,目前的最新版本為3。
l????????????? Mode:長度為3比特,表示NTP的工作模式。不同的值所表示的含義分別是:0未定義、1表示主動對等體模式、2表示被動對等體模式、3表示客戶模式、4表示服務器模式、5表示廣播模式或組播模式、6表示此報文為NTP控制報文、7預留給內部使用。
l????????????? Stratum:系統時鐘的層數,取值范圍為1~16,它定義了時鐘的準確度。層數為1的時鐘準確度最高,準確度從1到16依次遞減,層數為16的時鐘處于未同步狀態,不能作為參考時鐘。
l????????????? Poll:輪詢時間,即兩個連續NTP報文之間的時間間隔。
l????????????? Precision:系統時鐘的精度。
l????????????? Root Delay:本地到主參考時鐘源的往返時間。
l????????????? Root Dispersion:系統時鐘相對于主參考時鐘的最大誤差。
l????????????? Reference Identifier:參考時鐘源的標識。
l????????????? Reference Timestamp:系統時鐘最后一次被設定或更新的時間。
l????????????? Originate Timestamp:NTP請求報文離開發送端時發送端的本地時間。
l????????????? Receive Timestamp:NTP請求報文到達接收端時接收端的本地時間。
l????????????? Transmit Timestamp:應答報文離開應答者時應答者的本地時間。
l????????????? Authenticator:驗證信息。
NTP的工作模式
?設備可以采用多種NTP工作模式進行時間同步:
?????????? ? 客戶端/服務器模式
?????????? ??對等體模式
?????????? ?廣播模式
????????? ? 組播模式
用戶可以根據需要選擇合適的工作模式。在不能確定服務器或對等體IP地址、網絡中需要同步的設備很多等情況下,可以通過廣播或組播模式實現時鐘同步;客戶端/服務器和對等體模式中,設備從指定的服務器或對等體獲得時鐘同步,增加了時鐘的可靠性。
1. 客戶端/服務器模式
在客戶端/服務器模式中,客戶端向服務器發送時鐘同步報文,報文中的Mode字段設置為3(客戶模式)。服務器端收到報文后會自動工作在服務器模式,并發送應答報文,報文中的Mode字段設置為4(服務器模式)。客戶端收到應答報文后,進行時鐘過濾和選擇,并同步到優選的服務器。
在該模式下,客戶端能同步到服務器,而服務器無法同步到客戶端。
2. 對等體模式
?在對等體模式中,主動對等體和被動對等體之間首先交互Mode字段為3(客戶端模式)和4(服務器模式)的NTP報文。之后,主動對等體向被動對等體發送時鐘同步報文,報文中的Mode字段設置為1(主動對等體),被動對等體收到報文后自動工作在被動對等體模式,并發送應答報文,報文中的Mode字段設置為2(被動對等體)。經過報文的交互,對等體模式建立起來。主動對等體和被動對等體可以互相同步。如果雙方的時鐘都已經同步,則以層數小的時鐘為準
3. 廣播模式
在廣播模式中,服務器端周期性地向廣播地址255.255.255.255發送時鐘同步報文,報文中的Mode字段設置為5(廣播模式)。客戶端偵聽來自服務器的廣播報文。當客戶端接收到第一個廣播報文后,客戶端與服務器交互Mode字段為3(客戶模式)和4(服務器模式)的NTP報文,以獲得客戶端與服務器間的網絡延遲。之后,客戶端就進入廣播客戶端模式,繼續偵聽廣播報文的到來,根據到來的廣播報文對系統時鐘進行同步。
4. 組播模式
在組播模式中,服務器端周期性地向用戶配置的組播地址(若用戶沒有配置組播地址,則使用默認的NTP組播地址224.0.1.1)發送時鐘同步報文,報文中的Mode字段設置為5(組播模式)。客戶端偵聽來自服務器的組播報文。當客戶端接收到第一個組播報文后,客戶端與服務器交互Mode字段為3(客戶模式)和4(服務器模式)的NTP報文,以獲得客戶端與服務器間的網絡延遲。之后,客戶端就進入組播客戶模式,繼續偵聽組播報文的到來,根據到來的組播報文對系統時鐘進行同步。
NTP時間同步的實現
有了上述基礎知識后,我們就可以實現自己的時間同步工具了,下文附了一個簡單的C#的實現。
????class?NptClient
????{
????????IPAddress?ntpServer;
????????public?NptClient(IPAddress?ntpServer)
????????{
????????????this.ntpServer = ntpServer;
????????}
?
????????public?DateTime?GetServerTime()
????????{
????????????var?startTime =?DateTime.Now;
????????????var?ntpTime =?NTPData.Test(ntpServer);
????????????var?recvTime =?DateTime.Now;
?
????????????var?offset = ((ntpTime.ReceiveTimestamp - startTime) + (ntpTime.TransmitTimestamp - recvTime));
????????????offset = offset.Subtract(TimeSpan.FromSeconds(offset.TotalSeconds / 2));
?
????????????return?recvTime + offset;
????????}
????}
?
????[StructLayout(LayoutKind.Sequential)]
????class?NTPData
????{
????????byte?header = 0;
????????byte?Stratum = 1;???????????//系統時鐘的層數,取值范圍為1~16,它定義了時鐘的準確度
????????byte?Poll = 1;??????????????//輪詢時間,即兩個連續NTP報文之間的時間間隔
????????byte?Precision = 1;?????????//系統時鐘的精度
????????BigEndianUInt32?rootDelay;
????????BigEndianUInt32?referenceIdentifier;
????????BigEndianUInt32?ReferenceIdentifier;
?
????????public?NtpTime?ReferenceTimestamp {?get;?private?set; }
????????public?NtpTime?OriginateTimestamp {?get;?private?set; }
????????public?NtpTime?ReceiveTimestamp {?get;?private?set; }
????????public?NtpTime?TransmitTimestamp {?get;?private?set; }
?
????????public?NTPData()
????????{
????????????this.header = GetHeader();
????????}
?
????????byte?GetHeader()
????????{
????????????var?LI =?"00";
????????????var?VN =?"011";?????????//NTP的版本號為3
????????????var?Mode =?"011";???????//客戶模式
?
????????????return?Convert.ToByte(LI + VN + Mode, 2);
????????}
?
????????public?static?NTPData?Test(IPAddress?ntpServer)
????????{
????????????var?data =?MarshalExtend.GetData(new?NTPData());
?
????????????var?udp =?new?System.Net.Sockets.UdpClient();
????????????udp.Send(data, data.Length,?new?IPEndPoint(ntpServer, 123));
?
????????????var?ep =?new?IPEndPoint(IPAddress.Any, 0);
????????????var?replyData = udp.Receive(ref?ep);
?
????????????return?MarshalExtend.GetStruct<NTPData>(replyData, replyData.Length);
????????}
????}
?
????[StructLayout(LayoutKind.Sequential)]
????class?NtpTime
????{
????????BigEndianUInt32?seconds;
????????BigEndianUInt32?fraction;
?
????????static?readonly?DateTime?baseTime =?new?DateTime(1900, 1, 1, 0, 0, 0,?DateTimeKind.Utc);
?
????????public?static?implicit?operator?DateTime(NtpTime?time)
????????{
????????????/* rfc1305的ntp時間中,時間是用64bit來表示的,記錄的是1900年后的秒數(utc格式)
?????????????*?高32位是整數部分,低32位是小數部分?*/
?
????????????var?milliseconds = (int)(((double)time.fraction /?uint.MaxValue) * 1000);
????????????return?baseTime.AddSeconds(time.seconds).AddMilliseconds(milliseconds).ToLocalTime();
????????}
?
????????public?override?string?ToString()
????????{
????????????return?((DateTime)this).ToString("o");
????????}
????}
總結
以上是生活随笔為你收集整理的通过NTP协议进行时间同步的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu1870 愚人节的礼物
- 下一篇: 京东前端:三级列表页持续架构优化