2

I need to develop a app that gets the current time from a NTP Server but I can't find any example in Windows 8 Store App. If I try to use a normal C# class it doesn't work. Does anyone know how to solve this?

Den
  • 16,686
  • 4
  • 47
  • 87
user2263468
  • 51
  • 1
  • 5
  • "it doesn't work" is far too vague a description of the problem. Please edit your question to be more specific. – Jon Skeet Apr 09 '13 at 20:17
  • possible duplicate of [How to Query an NTP Server using C#?](http://stackoverflow.com/questions/1193955/how-to-query-an-ntp-server-using-c) – Nasreddine Jun 30 '15 at 15:05

3 Answers3

2

I would highly suggest avoiding string parsing out of a HTML page - a slight view format change will break your app.

Based on the example provided in this answer, here is the DatagramSocket adaptation to get a proper DateTime object:

DatagramSocket socket = new DatagramSocket();
socket.MessageReceived += socket_MessageReceived;
await socket.ConnectAsync(new HostName("time.windows.com"), "123");

using (DataWriter writer = new DataWriter(socket.OutputStream))
{
    byte[] container = new byte[48];
    container[0] = 0x1B;

    writer.WriteBytes(container);
    await writer.StoreAsync();
}

When the message is received, you can handle the incoming byte array through a built-in reader:

void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    using (DataReader reader = args.GetDataReader())
    {
        byte[] b = new byte[48];

        reader.ReadBytes(b);

        DateTime time = GetNetworkTime(b);
    }
}

GetNetworkTime is pretty much the same as in the example I mentioned, with the buffer passed as one of the arguments:

public static DateTime GetNetworkTime(byte[] rawData)
{
    //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(rawData, serverReplyTime);

    //Get the seconds fraction
    ulong fractPart = BitConverter.ToUInt32(rawData, 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)).AddMilliseconds((long)milliseconds);

    return networkDateTime;
}

// stackoverflow.com/a/3294698/162671
static uint SwapEndianness(ulong x)
{
    return (uint)(((x & 0x000000ff) << 24) +
                   ((x & 0x0000ff00) << 8) +
                   ((x & 0x00ff0000) >> 8) +
                   ((x & 0xff000000) >> 24));
}
Community
  • 1
  • 1
Den
  • 16,686
  • 4
  • 47
  • 87
1

I think this is what you want.

using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

private async Task<DateTime?> GetNistTime()
{
    DateTime? dateTime = null; 
    HttpClient httpClient = new HttpClient();
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://nist.time.gov/timezone.cgi?UTC/s/0"));
    HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    string text = await httpResponseMessage.Content.ReadAsStringAsync();
    if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
    {
        string html = await httpResponseMessage.Content.ReadAsStringAsync();
        string time = Regex.Match(html, @">\d+:\d+:\d+<").Value; //HH:mm:ss format
        string date = Regex.Match(html, @">\w+,\s\w+\s\d+,\s\d+<").Value; //dddd, MMMM dd, yyyy
        dateTime = DateTime.Parse((date + " " + time).Replace(">", "").Replace("<", ""));
    }
    return dateTime;
}
Farhan Ghumra
  • 15,180
  • 6
  • 50
  • 115
  • `HttpClient` has a `GetStringAsync` - no need for the `HttpRequestMessage`/`HttpResponseMessage` overhead. Other than that - direct string parsing is bound to cause issues in the long run, when the page structure changes. – Den May 05 '13 at 20:17
0

You need a StreamSocket and then implement the NTP procotol yourself. If you have an existing NTP C# class for classic Windows, you can maybe adapt the code to use the StreamSocket instead.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173