I work a lot with industrial operator panels. These panels have a integrated Real Time Clock that sadly doesn't include Daylight Saving Time. So every time we gain or lose an hour, the RTC of the panels needs to be changed manually. The positive thing about these panels is that they support the SNTP protocol to synchronise their RTC with a server. For a panel to actually sync it's RTC it needs to receive a SNTP packet that is broadcasted over the network by a SNTP server.
Looking at the SNTP protocol I thought it shouldn't be to difficult to code a very simple SNTP server myself. The demo application will periodically broadcast a SNTP packet containing the system date and time over the network.
Using the code
The demo application needs three command line arguments to function correctly.
- Broadcast IP address
- Broadcast port number (Default is 123 according to RFC2030)
- Broadcast interval (in seconds)
First we check if at least three command line arguments are provided.
If UBound(Environment.GetCommandLineArgs) = 3 Then
No further validation on these command line arguments is done. I leave this up to you.
The application uses the UdpClient class to broadcast the SNTP packet over the network.
Dim sntpServer As UdpClient
sntpServer = New UdpClient(Environment.GetCommandLineArgs(1), _
Now for the interesting part. (at least for me it was).
A loop is started that will build and send the actual SNTP packet.
The packet is 48 bytes in total but most of these could be left empty for my application. This might not fully comply with the RFC2030 but for me it worked fine.
The number of seconds between 01/01/1900 and the current system date/time need to be calculated and set to bytes 40 to 43 before the packet can be send.
Dim ts As TimeSpan = DateTime.Now - New DateTime(1900, 1, 1)
Dim tsHex As String = Hex(ts.TotalSeconds)
Dim packet(47) As Byte
packet(0) = 37 packet(1) = 2 packet(2) = 10 packet(3) = 250 packet(40) = Convert.ToByte(tsHex.Substring(0, 2), 16) packet(41) = Convert.ToByte(tsHex.Substring(2, 2), 16) packet(42) = Convert.ToByte(tsHex.Substring(4, 2), 16) packet(43) = Convert.ToByte(tsHex.Substring(6, 2), 16)
Now the packet is broadcasted and the settings are printed to the console.
Console.WriteLine("Packet send at: " & DateTime.Now)
Finally the thread is kept asleep during the interval time.
Thread.Sleep(Convert.ToInt16(Environment.GetCommandLineArgs(3)) * 1000)
25/07/2006, Version 1.0.0 : Initial post