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 }