现在的位置: 首页 > 综合 > 正文

C#获取Internet服务器的时间

2011年03月30日 ⁄ 综合 ⁄ 共 15867字 ⁄ 字号 评论关闭
using System;
using System.Net;
using System.Net.Sockets;

namespace SNTPTime
{
    
// 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>
    
/// SNTPTimeClient 的摘要说明。
    
/// 
    
/// 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.
    
/// 
    
/// 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 SNTPTimeClient
    {
        
// 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 0return _LeapIndicator.NoWarning;
                    
case 1return _LeapIndicator.LastMinute61;
                    
case 2return _LeapIndicator.LastMinute59;
                    
case 3:
                    
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:
                    
case 6:
                    
case 7:
                    
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 == 0return _Stratum.Unspecified;
                
else
                    
if (val == 1return _Stratum.PrimaryReference;
                    
else
                        
if (val <= 15return _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:
                    
case _Stratum.PrimaryReference:
                        val 
+= Convert.ToChar(NTPData[offReferenceID + 0]);
                        val 
+= Convert.ToChar(NTPData[offReferenceID + 1]);
                        val 
+= Convert.ToChar(NTPData[offReferenceID + 2]);
                        val 
+= Convert.ToChar(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
                        
////       {
                        
////        IPAddress RefAddr = new IPAddress(Address);
                        
////        IPHostEntry Host = DNS.GetHostByAddr(RefAddr);
                        
////        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
                        
////       long offset = TimeZone.CurrentTimeZone.GetUTCOffset(DateTime.Now);
                        
////       TimeSpan offspan = TimeSpan.FromTicks(offset);
                        
////       val = (time + offspan).ToString();
                        
////       break;
                        
////      default:
                        
////       val = "N/A";
                        
////     }
                        break;
                }

                return val;
            }
        }

        // Reference Timestamp
        public DateTime ReferenceTimestamp
        {
            
get
            {
                DateTime time 
= ComputeDate(GetMilliSeconds(offReferenceTimestamp));
                
// Take care of the time zone
                long offset = Convert.ToInt64(TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now));
                TimeSpan offspan 
= TimeSpan.FromTicks(offset);
                
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
                long offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Ticks;
                TimeSpan offspan 
= TimeSpan.FromTicks(offset);
                
return time + offspan;
            }
        }

        // Transmit Timestamp
        public DateTime TransmitTimestamp
        {
            
get
            {
                DateTime time 
= ComputeDate(GetMilliSeconds(offTransmitTimestamp));
                
// Take care of the time zone    
                long offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Ticks;
                TimeSpan offspan 
= TimeSpan.FromTicks(offset);
                
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(190011);
            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(190011000); // January 1, 1900 12:00 AM

            <

抱歉!评论已关闭.