实例介绍
【实例截图】
【核心代码】
/* * NTPClient * Copyright (C)2001 Valer BOCAN <vbocan@dataman.ro> * Last modified: June 29, 2001 * All Rights Reserved * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY, without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * To fully understand the concepts used herein, I strongly * recommend that you read the RFC 2030. * * NOTE: This example is intended to be compiled with Visual Studio .NET Beta 2 */ namespace TimeSync { using System; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; // Leap indicator field values public enum _LeapIndicator { NoWarning, // 0 - No warning LastMinute61, // 1 - Last minute has 61 seconds LastMinute59, // 2 - Last minute has 59 seconds Alarm // 3 - Alarm condition (clock not synchronized) } //Mode field values public enum _Mode { SymmetricActive, // 1 - Symmetric active SymmetricPassive, // 2 - Symmetric pasive Client, // 3 - Client Server, // 4 - Server Broadcast, // 5 - Broadcast Unknown // 0, 6, 7 - Reserved } // Stratum field values public enum _Stratum { Unspecified, // 0 - unspecified or unavailable PrimaryReference, // 1 - primary reference (e.g. radio-clock) SecondaryReference, // 2-15 - secondary reference (via NTP or SNTP) Reserved // 16-255 - reserved } /// <summary> /// NTPClient is a C# class designed to connect to time servers on the Internet. /// The implementation of the protocol is based on the RFC 2030. /// /// Public class members: /// /// LeapIndicator - Warns of an impending leap second to be inserted/deleted in the last /// minute of the current day. (See the _LeapIndicator enum) /// /// VersionNumber - Version number of the protocol (3 or 4). /// /// Mode - Returns mode. (See the _Mode enum) /// /// Stratum - Stratum of the clock. (See the _Stratum enum) /// /// PollInterval - Maximum interval between successive messages. /// /// Precision - Precision of the clock. /// /// RootDelay - Round trip time to the primary reference source. /// /// RootDispersion - Nominal error relative to the primary reference source. /// /// ReferenceID - Reference identifier (either a 4 character string or an IP address). /// /// ReferenceTimestamp - The time at which the clock was last set or corrected. /// /// OriginateTimestamp - The time at which the request departed the client for the server. /// /// ReceiveTimestamp - The time at which the request arrived at the server. /// /// Transmit Timestamp - The time at which the reply departed the server for client. /// /// RoundTripDelay - The time between the departure of request and arrival of reply. /// /// LocalClockOffset - The offset of the local clock relative to the primary reference /// source. /// /// Initialize - Sets up data structure and prepares for connection. /// /// Connect - Connects to the time server and populates the data structure. /// It can also set the system time. /// /// IsResponseValid - Returns true if received data is valid and if comes from /// a NTP-compliant time server. /// /// ToString - Returns a string representation of the object. /// /// ----------------------------------------------------------------------------- /// Structure of the standard NTP header (as described in RFC 2030) /// 1 2 3 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// |LI | VN |Mode | Stratum | Poll | Precision | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | Root Delay | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | Root Dispersion | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | Reference Identifier | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | | /// | Reference Timestamp (64) | /// | | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | | /// | Originate Timestamp (64) | /// | | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | | /// | Receive Timestamp (64) | /// | | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | | /// | Transmit Timestamp (64) | /// | | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | Key Identifier (optional) (32) | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | | /// | | /// | Message Digest (optional) (128) | /// | | /// | | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// /// ----------------------------------------------------------------------------- /// /// NTP Timestamp Format (as described in RFC 2030) /// 1 2 3 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | Seconds | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// | Seconds Fraction (0-padded) | /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// /// </summary> public class NTPClient { // NTP Data Structure Length private const byte NTPDataLength = 48; // NTP Data Structure (as described in RFC 2030) byte []NTPData = new byte[NTPDataLength]; // Offset constants for timestamps in the data structure private const byte offReferenceID = 12; private const byte offReferenceTimestamp = 16; private const byte offOriginateTimestamp = 24; private const byte offReceiveTimestamp = 32; private const byte offTransmitTimestamp = 40; // Leap Indicator public _LeapIndicator LeapIndicator { get { // Isolate the two most significant bits byte val = (byte)(NTPData[0] >> 6); switch(val) { case 0: return _LeapIndicator.NoWarning; case 1: return _LeapIndicator.LastMinute61; case 2: return _LeapIndicator.LastMinute59; case 3: goto default; default: return _LeapIndicator.Alarm; } } } // Version Number public byte VersionNumber { get { // Isolate bits 3 - 5 byte val = (byte)((NTPData[0] & 0x38) >> 3); return val; } } // Mode public _Mode Mode { get { // Isolate bits 0 - 3 byte val = (byte)(NTPData[0] & 0x7); switch(val) { case 0: goto default; case 6: goto default; case 7: goto default; default: return _Mode.Unknown; case 1: return _Mode.SymmetricActive; case 2: return _Mode.SymmetricPassive; case 3: return _Mode.Client; case 4: return _Mode.Server; case 5: return _Mode.Broadcast; } } } // Stratum public _Stratum Stratum { get { byte val = (byte)NTPData[1]; if(val == 0) return _Stratum.Unspecified; else if(val == 1) return _Stratum.PrimaryReference; else if(val <= 15) return _Stratum.SecondaryReference; else return _Stratum.Reserved; } } // Poll Interval public uint PollInterval { get { return (uint)Math.Round(Math.Pow(2, NTPData[2])); } } // Precision (in milliseconds) public double Precision { get { return (1000 * Math.Pow(2, NTPData[3])); } } // Root Delay (in milliseconds) public double RootDelay { get { int temp = 0; temp = 256 * (256 * (256 * NTPData[4] NTPData[5]) NTPData[6]) NTPData[7]; return 1000 * (((double)temp) / 0x10000); } } // Root Dispersion (in milliseconds) public double RootDispersion { get { int temp = 0; temp = 256 * (256 * (256 * NTPData[8] NTPData[9]) NTPData[10]) NTPData[11]; return 1000 * (((double)temp) / 0x10000); } } // Reference Identifier public string ReferenceID { get { string val = ""; switch(Stratum) { case _Stratum.Unspecified: goto case _Stratum.PrimaryReference; case _Stratum.PrimaryReference: val = (char)NTPData[offReferenceID 0]; val = (char)NTPData[offReferenceID 1]; val = (char)NTPData[offReferenceID 2]; val = (char)NTPData[offReferenceID 3]; break; case _Stratum.SecondaryReference: switch(VersionNumber) { case 3: // Version 3, Reference ID is an IPv4 address string Address = NTPData[offReferenceID 0].ToString() "." NTPData[offReferenceID 1].ToString() "." NTPData[offReferenceID 2].ToString() "." NTPData[offReferenceID 3].ToString(); try { IPHostEntry Host = Dns.GetHostByAddress(Address); val = Host.HostName " (" Address ")"; } catch(Exception) { val = "N/A"; } break; case 4: // Version 4, Reference ID is the timestamp of last update DateTime time = ComputeDate(GetMilliSeconds(offReferenceID)); // Take care of the time zone TimeSpan offspan = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); val = (time offspan).ToString(); break; default: val = "N/A"; break; } break; } return val; } } // Reference Timestamp public DateTime ReferenceTimestamp { get { DateTime time = ComputeDate(GetMilliSeconds(offReferenceTimestamp)); // Take care of the time zone TimeSpan offspan = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); return time offspan; } } // Originate Timestamp public DateTime OriginateTimestamp { get { return ComputeDate(GetMilliSeconds(offOriginateTimestamp)); } } // Receive Timestamp public DateTime ReceiveTimestamp { get { DateTime time = ComputeDate(GetMilliSeconds(offReceiveTimestamp)); // Take care of the time zone TimeSpan offspan = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); return time offspan; } } // Transmit Timestamp public DateTime TransmitTimestamp { get { DateTime time = ComputeDate(GetMilliSeconds(offTransmitTimestamp)); // Take care of the time zone TimeSpan offspan = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); return time offspan; } set { SetDate(offTransmitTimestamp, value); } } // Reception Timestamp public DateTime ReceptionTimestamp; // Round trip delay (in milliseconds) public int RoundTripDelay { get { TimeSpan span = (ReceiveTimestamp - OriginateTimestamp) (ReceptionTimestamp - TransmitTimestamp); return (int)span.TotalMilliseconds; } } // Local clock offset (in milliseconds) public int LocalClockOffset { get { TimeSpan span = (ReceiveTimestamp - OriginateTimestamp) - (ReceptionTimestamp - TransmitTimestamp); return (int)(span.TotalMilliseconds / 2); } } // Compute date, given the number of milliseconds since January 1, 1900 private DateTime ComputeDate(ulong milliseconds) { TimeSpan span = TimeSpan.FromMilliseconds((double)milliseconds); DateTime time = new DateTime(1900, 1, 1); time = span; return time; } // Compute the number of milliseconds, given the offset of a 8-byte array private ulong GetMilliSeconds(byte offset) { ulong intpart = 0, fractpart = 0; for(int i = 0; i <= 3; i ) { intpart = 256 * intpart NTPData[offset i]; } for(int i = 4; i<=7; i ) { fractpart = 256 * fractpart NTPData[offset i]; } ulong milliseconds = intpart * 1000 (fractpart * 1000) / 0x100000000L; return milliseconds; } // Compute the 8-byte array, given the date private void SetDate(byte offset, DateTime date) { ulong intpart = 0, fractpart = 0; DateTime StartOfCentury = new DateTime(1900, 1, 1, 0, 0, 0); // January 1, 1900 12:00 AM ulong milliseconds = (ulong)(date - StartOfCentury).TotalMilliseconds; intpart = milliseconds / 1000; fractpart=((milliseconds % 1000) * 0x100000000L) / 1000; ulong temp = intpart; for(int i = 3; i >= 0; i--) { NTPData[offset i] = (byte) (temp % 256); temp = temp / 256; } temp = fractpart; for(int i = 7; i >=4; i--) { NTPData[offset i] = (byte) (temp % 256); temp = temp / 256; } } // Initialize the NTPClient data private void Initialize() { // Set version number to 4 and Mode to 3 (client) NTPData[0] = 0x1B; // Initialize all other fields with 0 for(int i = 1; i < 48; i ) { NTPData[i] = 0; } // Initialize the transmit timestamp TransmitTimestamp = DateTime.Now; } public NTPClient(string host) { TimeServer = host; } // Connect to the time server and update system time public void Connect(bool UpdateSystemTime) { try { // Resolve server address IPHostEntry hostadd = Dns.Resolve(TimeServer); IPEndPoint EPhost = new IPEndPoint(hostadd.AddressList[0], 123); //Connect the time server UdpClient TimeSocket = new UdpClient(); TimeSocket.Connect(EPhost); // Initialize data structure Initialize(); TimeSocket.Send(NTPData, NTPData.Length); NTPData = TimeSocket.Receive(ref EPhost); if(!IsResponseValid()) { throw new Exception("Invalid response from " TimeServer); } ReceptionTimestamp = DateTime.Now; } catch(SocketException e) { throw new Exception(e.Message); } // Update system time if(UpdateSystemTime) { SetTime(); } } // Check if the response from server is valid public bool IsResponseValid() { if(NTPData.Length < NTPDataLength || Mode != _Mode.Server) { return false; } else { return true; } } // Converts the object to string public override string ToString() { string str; str = "Leap Indicator: "; switch(LeapIndicator) { case _LeapIndicator.NoWarning: str = "No warning"; break; case _LeapIndicator.LastMinute61: str = "Last minute has 61 seconds"; break; case _LeapIndicator.LastMinute59: str = "Last minute has 59 seconds"; break; case _LeapIndicator.Alarm: str = "Alarm Condition (clock not synchronized)"; break; } str = "\r\nVersion number: " VersionNumber.ToString() "\r\n"; str = "Mode: "; switch(Mode) { case _Mode.Unknown: str = "Unknown"; break; case _Mode.SymmetricActive: str = "Symmetric Active"; break; case _Mode.SymmetricPassive: str = "Symmetric Pasive"; break; case _Mode.Client: str = "Client"; break; case _Mode.Server: str = "Server"; break; case _Mode.Broadcast: str = "Broadcast"; break; } str = "\r\nStratum: "; switch(Stratum) { case _Stratum.Unspecified: case _Stratum.Reserved: str = "Unspecified"; break; case _Stratum.PrimaryReference: str = "Primary Reference"; break; case _Stratum.SecondaryReference: str = "Secondary Reference"; break; } str = "\r\nLocal time: " TransmitTimestamp.ToString(); str = "\r\nPrecision: " Precision.ToString() " ms"; str = "\r\nPoll Interval: " PollInterval.ToString() " s"; str = "\r\nReference ID: " ReferenceID.ToString(); str = "\r\nRoot Dispersion: " RootDispersion.ToString() " ms"; str = "\r\nRound Trip Delay: " RoundTripDelay.ToString() " ms"; str = "\r\nLocal Clock Offset: " LocalClockOffset.ToString() " ms"; str = "\r\n"; return str; } // SYSTEMTIME structure used by SetSystemTime [StructLayoutAttribute(LayoutKind.Sequential)] private struct SYSTEMTIME { public short year; public short month; public short dayOfWeek; public short day; public short hour; public short minute; public short second; public short milliseconds; } [DllImport("kernel32.dll")] static extern bool SetLocalTime(ref SYSTEMTIME time); // Set system time according to transmit timestamp private void SetTime() { SYSTEMTIME st; DateTime trts = TransmitTimestamp; st.year = (short)trts.Year; st.month = (short)trts.Month; st.dayOfWeek = (short)trts.DayOfWeek; st.day = (short)trts.Day; st.hour = (short)trts.Hour; st.minute = (short)trts.Minute; st.second = (short)trts.Second; st.milliseconds = (short)trts.Millisecond; SetLocalTime(ref st); } // The URL of the time server we're connecting to private string TimeServer; } }
标签: 时间
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论