/******************************************************************************* Created by Saumit S. Sheth (saumit@execpc.com) April 15, 2003 This program gets the official date and time from the NIST (ITS) timeserver and updates the system time on your computer. This program was only tested on Windows 2000 Professional. *********************************************************************************/ using System; using System.Drawing; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; public class NISTTime { Form mainForm; // The window that contains everything Label timeLabel; // The label that displays official time MainMenu mainMenu; MenuItem fileMenu, fileExitMenu, fileGetMenu; // The file menu and menu items public struct SystemTime // win32 struct { public short wYear; public short wMonth; public short wDayOfWeek; public short wDay; public short wHour; public short wMinute; public short wSecond; public short wMilliseconds; }; [DllImport("kernel32.dll")] // function imported from kernel32.dll public static extern bool SetSystemTime(ref SystemTime systime); // win32 API function declaration /*---------------------------------------------------------------------- NISTTime() This constructor creates the window, label, and menu objects, and event handlers. ------------------------------------------------------------------------*/ public NISTTime() { mainForm = new Form(); timeLabel = new Label(); mainMenu = new MainMenu(); fileMenu = new MenuItem("File"); fileExitMenu = new MenuItem("Exit"); fileGetMenu = new MenuItem("Get Official Time and Update"); mainForm.Text = "NIST Internet Time Service"; // set title of window mainForm.MaximizeBox = false; // don't need these buttons mainForm.MinimizeBox = false; timeLabel.Location = new Point(0, 10); // set position of label timeLabel.Width = mainForm.Width - 20; timeLabel.Font = new Font("Ariel", 11); // set label font mainMenu.MenuItems.Add(fileMenu); // create file menu fileMenu.MenuItems.Add(fileGetMenu); // create file menu items fileMenu.MenuItems.Add(fileExitMenu); fileGetMenu.Click += new EventHandler(this.GetTimeClicked); // Add event handler when menu item clicked fileExitMenu.Click += new EventHandler(this.ExitClicked); mainForm.Controls.Add(timeLabel); // add objects to window mainForm.Menu = mainMenu; mainForm.Height = 3 * timeLabel.Height + 20; mainForm.ShowDialog(); // display window } /*---------------------------------------------------------------------- GetTimeClicked(Object, EventArgs) This is the event handler for when the "File->Get Set System Time & Update" menu item is clicked. This follows the Daytime Protocol (RFC 867). Visit www.ietf.org for more information. A socket is created to the timeserver IP address at port 13. I hard-coded the main timeserver address, but other timeservers can be used, such as: time-a.nist.gov time-b.nist.gov utcnist.colorado.edu nist1.datum.com nist1-ny.glassey.com nist1.aol-ca.truetime.com Anything (I just send the "hello" string) can be sent to the timeserver. What's returned (in ASCII) is: JJJJJ YR-MO-DA HH:MM:SS TT L H msADV UTC(NIST) OTM where JJJJJ is the Modified Julian Date, YR-MO-DA is the date, HH:MM:SS is the time, TT is a 2-digit indicator whether it is ST(00) or DST(50), L is whether a leap second will be added or subtracted at the end of the current month, H indicates health of server, msADV is num of ms NIST advances to compensate for network delays, UTC is a label always included, OTM is the on-time-marker, an '*'. Once the data is received, the socket is closed. The information is parsed and a label displays the information. The SetSystemTime API function is called and the system time is updated. -------------------------------------------------------------------------*/ private void GetTimeClicked(Object sender, EventArgs e) { DateTime official, localtime; // official time from timeserver, localtime version string returndata = null; // bytes returned from timeserver string[] dates = new string[4]; // year, month, day string[] times = new string[4]; // hour, minute, second string[] tokens = new string[11]; // bytes tokenized TcpClient tcpclient = new TcpClient(); // create new socket object try { tcpclient.Connect("time.nist.gov", 13); // try to connect to timeserver NetworkStream networkStream = tcpclient.GetStream(); // socket stream if (networkStream.CanWrite && networkStream.CanRead) // stream is ready { Byte[] sendBytes = Encoding.ASCII.GetBytes("Hello"); // the hello string, Can be anything! networkStream.Write(sendBytes, 0, sendBytes.Length); // send to timeserver byte[] bytes = new byte[tcpclient.ReceiveBufferSize]; networkStream.Read(bytes, 0, (int) tcpclient.ReceiveBufferSize); // the official timeserver data returndata = Encoding.ASCII.GetString(bytes); // cast as ASCII string } tcpclient.Close(); // close socket } catch(Exception excep) { MessageBox.Show(excep.ToString()); // display exception to user return; // if exception occurred don't continue } tokens = returndata.Split(' '); // the timeserver data space parsed dates = tokens[1].Split('-'); // the date info hypen parsed times = tokens[2].Split(':'); // the time info colon parsed official = new DateTime(Int32.Parse(dates[0]) + 2000, Int32.Parse(dates[1]), Int32.Parse(dates[2]), Int32.Parse(times[0]), Int32.Parse(times[1]), Int32.Parse(times[2])); // create a new datetime object with these values localtime = TimeZone.CurrentTimeZone.ToLocalTime(official); // UTC converted to computer's time zone timeLabel.Text = localtime.ToLongDateString() + " " + localtime.ToLongTimeString(); // display official date and time SystemTime systime = new SystemTime(); // create systemtime object systime.wYear = (short)official.Year; // set struct with correct values systime.wMonth = (short)official.Month; systime.wDay = (short)official.Day; systime.wHour = (short)official.Hour; systime.wMinute = (short)official.Minute; systime.wSecond = (short)official.Second; SetSystemTime(ref systime); // win32 API function to set system time (in UTC) } /*---------------------------------------------------------------------- ExitClicked(Object, EventArgs) This event handler halts the program and quits. ------------------------------------------------------------------------*/ private void ExitClicked(Object sender, EventArgs e) { Application.Exit(); // Quit program } /*---------------------------------------------------------------------- Main(string[]) The entrypoint of the program ------------------------------------------------------------------------*/ public static void Main(string[] args) { NISTTime nisttime = new NISTTime(); // Create new instance of object } }