//using System;
//using System.Collections.Generic;
//using System.Text;
//using System.Net;
//using System.Net.Sockets;
//using System.Runtime.InteropServices;
//namespace NewLife.Net.Application
//{
// /// <summary>
// /// Leap indicator
// /// </summary>
// 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)
// }
// /// <summary>
// /// Mode
// /// </summary>
// 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
// }
// /// <summary>
// /// Stratum
// /// </summary>
// 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.
// ///
// /// -----------------------------------------------------------------------------
// /// 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;
// /// <summary>
// /// Warns of an impending leap second to be inserted/deleted in the last minute of the current day. (See the _LeapIndicator enum)
// /// </summary>
// 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;
// }
// }
// }
// /// <summary>
// /// Version number of the protocol (3 or 4).
// /// </summary>
// public byte VersionNumber
// {
// get
// {
// // Isolate bits 3 - 5
// byte val = (byte)((NTPData[0] & 0x38) >> 3);
// return val;
// }
// }
// /// <summary>
// /// Returns mode. (See the _Mode enum)
// /// </summary>
// 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;
// }
// }
// }
// /// <summary>
// /// Stratum of the clock. (See the _Stratum enum)
// /// </summary>
// 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;
// }
// }
// /// <summary>
// /// Maximum interval between successive messages.
// /// </summary>
// public uint PollInterval
// {
// get
// {
// return (uint)Math.Round(Math.Pow(2, NTPData[2]));
// }
// }
// /// <summary>
// /// Precision of the clock.
// /// </summary>
// public double Precision
// {
// get
// {
// return (1000 * Math.Pow(2, NTPData[3]));
// }
// }
// /// <summary>
// /// Round trip time to the primary reference source.
// /// </summary>
// public double RootDelay
// {
// get
// {
// int temp = 0;
// temp = 256 * (256 * (256 * NTPData[4] + NTPData[5]) + NTPData[6]) + NTPData[7];
// return 1000 * (((double)temp) / 0x10000);
// }
// }
// /// <summary>
// /// Nominal error relative to the primary reference source.
// /// </summary>
// public double RootDispersion
// {
// get
// {
// int temp = 0;
// temp = 256 * (256 * (256 * NTPData[8] + NTPData[9]) + NTPData[10]) + NTPData[11];
// return 1000 * (((double)temp) / 0x10000);
// }
// }
// /// <summary>
// /// Reference identifier (either a 4 character string or an IP address).
// /// </summary>
// 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;
// }
// }
// /// <summary>
// /// The time at which the clock was last set or corrected.
// /// </summary>
// 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;
// }
// }
// /// <summary>
// /// The time at which the request departed the client for the server.
// /// </summary>
// public DateTime OriginateTimestamp
// {
// get
// {
// return ComputeDate(GetMilliSeconds(offOriginateTimestamp));
// }
// }
// /// <summary>
// /// The time at which the request arrived at the server.
// /// </summary>
// 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;
// }
// }
// /// <summary>
// /// The time at which the reply departed the server for client.
// /// </summary>
// 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);
// }
// }
// /// <summary>
// /// ReceptionTimestamp
// /// </summary>
// public DateTime ReceptionTimestamp;
// /// <summary>
// /// The time between the departure of request and arrival of reply.
// /// </summary>
// public int RoundTripDelay
// {
// get
// {
// TimeSpan span = (ReceiveTimestamp - OriginateTimestamp) + (ReceptionTimestamp - TransmitTimestamp);
// return (int)span.TotalMilliseconds;
// }
// }
// /// <summary>
// /// Local clock offset (in milliseconds)
// /// </summary>
// 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;
// }
// }
// /// <summary>
// /// Sets up data structure and prepares for connection.
// /// </summary>
// 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;
// }
// /// <summary>
// /// 实例化
// /// </summary>
// /// <param name="host"></param>
// public NTPClient(string host)
// {
// TimeServer = host;
// }
// /// <summary>
// /// Connects to the time server and populates the data structure.It can also set the system time.
// /// </summary>
// /// <param name="UpdateSystemTime"></param>
// 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();
// }
// }
// /// <summary>
// /// Returns true if received data is valid and if comes from a NTP-compliant time server.
// /// </summary>
// /// <returns></returns>
// public bool IsResponseValid()
// {
// if (NTPData.Length < NTPDataLength || Mode != _Mode.Server)
// {
// return false;
// }
// else
// {
// return true;
// }
// }
// /// <summary>
// /// Returns a string representation of the object.
// /// </summary>
// /// <returns></returns>
// 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;
// }
// /// <summary>
// /// 系统时间结构体
// /// </summary>
// [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;
// }
//}
|