Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Query an NTP Server using C#?

Tags:

c#

datetime

ntp

All I need is a way to query an NTP Server using C# to get the Date Time of the NTP Server returned as either a string or as a DateTime.

How is this possible in its simplest form?

like image 205
JL. Avatar asked Jul 28 '09 13:07

JL.


People also ask

What is an NTP query?

Description. ntpq is used to query NTP servers which implement the recommended NTP mode 6 control message format about current state and to request changes in that state. The program may be run either in interactive mode or controlled using command line arguments.

What is Ntpdate offset?

Offset: Offset generally refers to the difference in time between an external timing reference and time on a local machine. The greater the offset, the more inaccurate the timing source is. Synchronised NTP servers will generally have a low offset. Offset is generally measured in milliseconds.


2 Answers

Since the old accepted answer got deleted (It was a link to a Google code search results that no longer exist), I figured I could answer this question for future reference :

public static DateTime GetNetworkTime() {     //default Windows time server     const string ntpServer = "time.windows.com";      // NTP message size - 16 bytes of the digest (RFC 2030)     var ntpData = new byte[48];      //Setting the Leap Indicator, Version Number and Mode values     ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)      var addresses = Dns.GetHostEntry(ntpServer).AddressList;      //The UDP port number assigned to NTP is 123     var ipEndPoint = new IPEndPoint(addresses[0], 123);     //NTP uses UDP      using(var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))     {         socket.Connect(ipEndPoint);          //Stops code hang if NTP is blocked         socket.ReceiveTimeout = 3000;               socket.Send(ntpData);         socket.Receive(ntpData);         socket.Close();     }      //Offset to get to the "Transmit Timestamp" field (time at which the reply      //departed the server for the client, in 64-bit timestamp format."     const byte serverReplyTime = 40;      //Get the seconds part     ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);      //Get the seconds fraction     ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);      //Convert From big-endian to little-endian     intPart = SwapEndianness(intPart);     fractPart = SwapEndianness(fractPart);      var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);      //**UTC** time     var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);      return networkDateTime.ToLocalTime(); }  // stackoverflow.com/a/3294698/162671 static uint SwapEndianness(ulong x) {     return (uint) (((x & 0x000000ff) << 24) +                    ((x & 0x0000ff00) << 8) +                    ((x & 0x00ff0000) >> 8) +                    ((x & 0xff000000) >> 24)); } 

Note: You will have to add the following namespaces

using System.Net; using System.Net.Sockets; 
like image 200
Nasreddine Avatar answered Sep 22 '22 16:09

Nasreddine


This is a optimized version of the function which removes dependency on BitConverter function and makes it compatible with NETMF (.NET Micro Framework)

public static DateTime GetNetworkTime() {     const string ntpServer = "pool.ntp.org";     var ntpData = new byte[48];     ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)      var addresses = Dns.GetHostEntry(ntpServer).AddressList;     var ipEndPoint = new IPEndPoint(addresses[0], 123);     var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);      socket.Connect(ipEndPoint);     socket.Send(ntpData);     socket.Receive(ntpData);     socket.Close();      ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43];     ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47];      var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);     var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);      return networkDateTime; } 
like image 20
GonzaloG Avatar answered Sep 18 '22 16:09

GonzaloG