1        //available ntp servers
  2        /*
  3         *美国apple: time.asia.apple.com 
  4         *美国 Microsoft公司 131.107.1.10
  5         *新加坡 203.117.180.36
  6         *美国 clock.via.net 
  7         *上海交通大学 ntp.sjtu.edu.cn
  8         *美国 马萨诸塞州大波士顿区麻省理工学院 18.145.0.30 
  9         *德国 柏林工业大学130.149.17.21
 10         *美国 宾夕法尼亚州立大学 128.118.46.3
 11         *日本 福冈大学 133.100.9.2
 12         *澳大利亚 堪培拉大学137.92.140.80
 13         */
 14         /// <summary>
 15         /// get current date time from net work.
 16         /// </summary>
 17         /// <returns></returns>
 18         private DateTime GetLocalDateTime(int timeZone)
 19         {
 20             DateTime? utcDateTime = null;
 21             //set ntp servers.
 22             string[] ntpServer = 
 23             { 
 24               "time.asia.apple.com",
 25               "ntp.sjtu.edu.cn",
 26               "131.107.1.10 ",
 27               "203.117.180.36",
 28               "130.149.17.21",
 29               "133.100.9.2",
 30               "137.92.140.80"
 31             };
 32             //get utc from ntp server.
 33             for (int ntpServerIndex = 0; ntpServerIndex < ntpServer.Length; ntpServerIndex++)
 34             {
 35                 try
 36                 {
 37                     utcDateTime = NTPHelper.GetUTCDate(ntpServer[ntpServerIndex]);
 38                     //if success to get utc,Jump out the loop
 39                     break;
 40                 }
 41                 catch
 42                 {
 43                     //if throw exception,get utc from another ntp server.
 44                     continue;
 45                 }
 46             }
 47             if (utcDateTime != null)
 48             {
 49                 return utcDateTime.Value.AddHours(timeZone);
 50             }
 51             else
 52             {
 53                 throw new Exception("can't get utc");
 54             }
 55         }
 56 
 57     public class NTPHelper
 58     {
 59         public static DateTime GetUTCDate(string ntpServer)
 60         {
 61             // NTP message size - 16 bytes of the digest (RFC 2030)
 62             var ntpData = new byte[48];
 63             //Setting the Leap Indicator, Version Number and Mode values
 64             //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
 65             ntpData[0] = 0x1B;
 66             try
 67             {
 68                 var addresses = Dns.GetHostEntry(ntpServer).AddressList;
 69                 //The UDP port number assigned to NTP is 123
 70                 var ipEndPoint = new IPEndPoint(addresses[0], 123);
 71                 //NTP uses UDP
 72                 var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 73 
 74                 socket.Connect(ipEndPoint);
 75                 //Stops code hang if NTP is blocked
 76                 socket.ReceiveTimeout = 3000;
 77 
 78                 socket.Send(ntpData);
 79                 socket.Receive(ntpData);
 80                 socket.Close();
 81                 //Offset to get to the "Transmit Timestamp" field (time at which the reply 
 82                 //departed the server for the client, in 64-bit timestamp format."
 83                 const byte serverReplyTime = 40;
 84                 //Get the seconds part
 85                 ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
 86                 //Get the seconds fraction
 87                 ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
 88                 //Convert From big-endian to little-endian
 89                 intPart = SwapEndianness(intPart);
 90                 fractPart = SwapEndianness(fractPart);
 91 
 92                 var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
 93                 //**UTC** time
 94                 var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);
 95 
 96                 return networkDateTime;
 97             }
 98             catch(Exception ex)
 99             {
100                 throw ex;
101             }
102         }
103 
104         // stackoverflow.com/a/3294698/162671
105         static uint SwapEndianness(ulong x)
106         {
107             return (uint)(((x & 0x000000ff) << 24) +
108                            ((x & 0x0000ff00) << 8) +
109                            ((x & 0x00ff0000) >> 8) +
110                            ((x & 0xff000000) >> 24));
111         }
112     }

 

posted on 2014-09-19 11:08  JustYong  阅读(695)  评论(0编辑  收藏  举报