(转)C#获取Internet服务器的时间

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   0 return  _LeapIndicator.NoWarning;
                    
case   1 return  _LeapIndicator.LastMinute61;
                    
case   2 return  _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  ==   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:
                    
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( 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;
        }

        
//  Connect to the time server
         public   void  Connect()
        {
            
try
            {
                IPAddress hostadd 
=  IPAddress.Parse(TimeServer);
                IPEndPoint EPhost 
=   new  IPEndPoint(hostadd, Convert.ToInt32(TimePort));

                UdpClient TimeSocket 
=   new  UdpClient();
                TimeSocket.Connect(EPhost);
                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);
            }
        }

        
//  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;
        }

        
//  The URL of the time server we're connecting to
         private   string  TimeServer;
        
private   string  TimePort;

        
public  SNTPTimeClient( string  host,  string  port)
        {
            TimeServer 
=  host;
            TimePort 
=  port;
        }
    }
}


调用:

            SNTPTime.SNTPTimeClient client  =   new  SNTPTime.SNTPTimeClient( " 210.72.145.44 " " 123 " );
            client.Connect();
            
string  strTest  =  client.ToString();

 

原文摘自: http://www.cnblogs.com/easydata/archive/2008/04/01/1132917.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值