NTP

The project contains a NTP implementation following RFC 5905. The following contains a quick introduction to this feature and some basic code snippets. If you're interested in a full sample that goes beyond the snippets shown here, download the current source code of the project which contains a sample project.

Why?

Windows Phone has no public API to access internet time servers. Even over internet connections it's possible to retrieve very accurate (as in: down to few milliseconds) time values that allow clock synchronization across multiple devices. This is an interesting option if you want to e.g. process data received from multiple phones on a central server and need to compare the generated timestamps accurately (think multiplayer gaming, for example). Please note that Windows Phone also has no way of programmatically setting the system clock though, so even you can retrieve the time from an NTP server, there is no way of adjusting the system time based on this from your application. You can however use that information to create accurate timestamps in your application.

How

All the NTP related features are located in the namespace PhoneNetTools.Ntp. The central class is SntpClient, which is an SNTP implementation. The infrastructure to support full NTP is already laid out, but SNTP should be sufficient for all kinds of scenarios on the phone. The SntpClient class allows you to either send a generic NTP message to a time server and consume the result, or to use one of the convenience methods that send pre-configured messages to retrieve the server time without the need to perform any additional configuration that requires knowledge about NTP.

The following is a sample snippet of using the convenience GetTimeAsync method:

private SntpClient _client = new SntpClient();

// [...]

// hook the completed event of the SNTP client, 
// for example in your page's constructor
_client.Completed += Client_Completed;

// [...]

// create the endpoint and invoke the SNTP client's GetTimeAsync convenience method.
// you can also use one of the other overloads that takes only the host name or IP address,
// or even the generic methods that allow sending a NTP message you've built and set up yourself
var endPoint = new DnsEndPoint(timeServer, Constants.NtpPort);
_client.GetTimeAsync(endPoint);

The Completed event handler is invoked on a background thread, so make sure to marshal back to the UI thread if you need to access UI elements. You should check for any errors, and if there are none, you can consume the result. The most interesting value should be the LocalClockOffset property of the returned server message provided in the event arguments:

private void Client_Completed(object sender, SntpResultEventArgs e)
{
    // the events of the SNTP client are raised on a background thread
    // => use something like this to marshal execution back to the UI thread
    //    if you need to access UI elements
    // => OR implement proper locking or similar if you don't need to access 
    //    the UI, but access shared resources
    if (!CheckAccess())
    {
        Dispatcher.BeginInvoke(() => Client_Completed(sender, e));
    }
    else
    {
        // first check for errors
        if (e.Error != SocketError.Success)
        {
            MessageBox.Show("Error while fetching time from server: " + e.Error);
            return;
        }

        // if there was no error, we have an offset here
        var offset = e.Message.LocalClockOffset;
		
        // do something with that result
    }
}

You can now use the offset to adjust the local time (e.g. returned by DateTime.Now) to produce accurate timestamps.

Last edited Nov 11, 2011 at 12:04 PM by Mister_Goodcat, version 1

Comments

No comments yet.