Topic : PC Clock Synchronizing using HTTP
Author : Alex Rest
Page : 1

PC CLOCK SYNCHRONIZING USING HTTP PROTOCOL
by Alex Rest


Environment : VC6, VC7, Windows 9x/NT/2000/XP with IE4 or higher

Introduction

     The standard way of synchronization PC clock though Internet is using special Network Time Protocol (NTP). It was mainly developed at the Delaware University in the United States. Tree versions of NTP were defined: the first on 1988, the second on 1989, the third on 1992. The current version is the third that is compatible with the previous ones. To make the use of NTP on personal computers easier, on 1995 it was defined the Simplified NTP (SNTP).
Unfortunately standard windows software of Win95/98/ME/NT/W2KPro is not support synchronization PC Clock using Internet.
     When I solved to create synchronization program I chose HTTP (Hypertext Transfer Protocol) instead SNTP. I like it because it is more universal. All WWW pages that you watch are brought to the screen of your PC using this protocol. I created the program and called it "For Atomic Synchronization".
     There are a lot of government and scientific sites that shows atomic time. There is small delay of site opening and receiving information. I explore my program "For Atomic Synchronization" during some month. Net delay seldom overloads 2 seconds. I take half delay and correct time according it. As result I cannot find difference between my PC clock time and time that I watch on TV Screen ore hear in FM receiver.
     As a time source I use site of Time Service Department of U.S. Naval Observatory. It is official Source of Time for the Department of Defense and the Standard of Time for the United States. I have tested some others. They all works well but this one have very simple format. The WWW page size is only 603 symbols (including html tags). Try this URL: http://tycho.usno.navy.mil/cgi-bin/timer.pl and you will see same information as my program gets.

     "For Atomic Synchronization" program is big enough for describing. To demonstrate main principles of synchronization I create small project that is described below.

Reading WWW sites using Win API

     Modern Windows versions with Internet Explorer 4.0 or later have very nice Internet API functions. You need not work with such low terms as TCP/IP protocol, sockets, ports, DNS, http protocol and etc. In this example I use API functions instead same MFC classes because they are more universal and you can easy translate this code to VB ore to other program language.
     All API functions work as chains. The first function opens Windows resource and returns its number that is named "handle". Next function must use this handle. It could return other handle, return code or something else. You mast close handle when you need not it any more.

Look at the function CBSAtomicEduDlg::OnSyncro (see code below). It works with Internet as user:
1) Function InternetOpen is opens Internet. If you are off line now it opens Dialup connection window.
2) Function InternetOpenUrl retrieves the site that you are looking for.
3) Function InternetReadFile reads the site into the text buffer.


It is all! You have the text of site! Do with it that you want!


And do not forget check errors and close handles (function InternetCloseHandle).
Such a way you can explore any information in Internet!

Do not forget to include in the project "Wininet.h" file !

Universal and Local time

     My watch show 02:00 am when there is midnight in London. The sun is rolling around the Earth so there is different time in different places. (P.s. I heard about Copernicus and Jordano Bruno). To define what time we use in the place where we are, we use special time zone. Time zones are not strips on a globe. They were created not only according geographical longitude but according states (countries) delimiters too. If you want to synchronize your PC using Internet you must have right zone information in your Operating System. You had set it while was installing OS and can change any time later.
     If you know Universal time (GMT) and your time zone you can ease calculate your local time.
Look at function LocalZoneTime (see code bellow). It calculate Universal time to Local time using time zone information. Universal time I got from WWW site. All information about time zone that I need I received by calling Win API function GetTimeZoneInformation. Look at Microsoft help to understand how use this information. The information includes DST (daylight saving time) correction.

Links

http://www.brigsoft.com/bsatomic/ - All around synchronization include link to this article, project download links, "For Atomic Synchronization" program download link and description.
http://tycho.usno.navy.mil/cgi-bin/timer.pl - official Source of Time for the Department of Defense and the Standard of Time for the United States.

Source VC++ code

It is a part of Dialog based MFC project, that makes time synchronization.

// LocalZoneTime function calculate Local time using Universal time.
// Time zone information is gotten from Windows using
// GetTimeZoneInformation API function (see MSDN for mo information).
// The function support DST time.
// Created by Alex.
void LocalZoneTime(const SYSTEMTIME& tmUniversal, SYSTEMTIME& tmLocal)
{

   TIME_ZONE_INFORMATION TZI;
   DWORD retCode = GetTimeZoneInformation(&TZI);

   int iStandardMonth = TZI.StandardDate.wMonth;
   int iDaylightMonth = TZI.DaylightDate.wMonth;

   long nZoneCorrection = TZI.Bias;

   if( retCode == TIME_ZONE_ID_STANDARD){
       nZoneCorrection = nZoneCorrection + TZI.StandardBias;
   }
   else if( retCode == TIME_ZONE_ID_DAYLIGHT){
       nZoneCorrection = nZoneCorrection + TZI.DaylightBias;
   }
   else{
       ASSERT(0);
   }

   nZoneCorrection = -nZoneCorrection;
   int nTotalMinutes = tmUniversal.wHour * 60 + tmUniversal.wMinute + nZoneCorrection;
   if(nTotalMinutes < 0){
       nTotalMinutes+=24*60;
   }
   if(nTotalMinutes>24*60){
       nTotalMinutes-=24*60;
   }

   tmLocal.wHour = nTotalMinutes /60;
   tmLocal.wMinute = nTotalMinutes - tmLocal.wHour*60;
   tmLocal.wSecond = tmUniversal.wSecond;

   }

   // OnSyncro is called after ID_SYNCRO dialog button pressing.
   // It opens Internet connection, receives Universal Time,
   // calculates Local Time and set it in Windows.
   // Created by Alex.

   void CBSAtomicEduDlg::OnSyncro()
   {

   // Open Internet connection.
   HINTERNET hInternet = ::InternetOpen("BSAtomicEdu", INTERNET_OPEN_TYPE_PRECONFIG , NULL, NULL, 0);
   if(!hInternet){
       AfxMessageBox( "Internet open error! Test your system and try again.", MB_OK | MB_ICONERROR );
       return;
   }

   // Open site of U.S. Naval Observatory.
   unsigned long Context = 777;
   HINTERNET hHttp = ::InternetOpenUrl(hInternet, "http://tycho.usno.navy.mil/cgi-bin/timer.pl",
   NULL, -1L, INTERNET_FLAG_RELOAD, Context);

   if(!hHttp){

   AfxMessageBox("URL open error!", MB_OK | MB_ICONERROR );


   if(hInternet){
       InternetCloseHandle(hInternet);
   }
   return;

   }

   // Read the time from site
   CString buff(' ',1024);
   unsigned long NumberOfBytesRead = 0;
   BOOL bRet = ::InternetReadFile(hHttp, (void *)((LPCTSTR)buff), 1024L, &NumberOfBytesRead);

   // Close Internet connection.
   if(hHttp){
       InternetCloseHandle(hHttp);
   }
   if(hInternet){
       InternetCloseHandle(hInternet);
   }

   // Is received information correct?
   if(!bRet){
       AfxMessageBox( "URL reading error! Test internet connection and try again.", MB_OK | MB_ICONERROR );
       return;
   }
   if(NumberOfBytesRead != 603){
       AfxMessageBox( "Unrecognized communication error!", MB_OK | MB_ICONERROR );
   return;
   }


   // Parse Universal time from string buffer to SYSTEMTIME struct.
   SYSTEMTIME tmUniversal, tmLocal, dtOldTime;
   ZeroMemory(&tmUniversal,sizeof(tmUniversal));
   GetLocalTime(&tmLocal);
   dtOldTime = tmLocal;

   tmUniversal.wHour = atoi((LPCTSTR)buff.Mid(111,2));
   tmUniversal.wMinute = atoi((LPCTSTR)buff.Mid(114,2));
   tmUniversal.wSecond = atoi((LPCTSTR)buff.Mid(117,2));

   // Calculate Local Time using received Universal Time.
   LocalZoneTime(tmUniversal, tmLocal);

   // Make Windows time correction.
   SetLocalTime(&tmLocal);

   // Show report dialog box.
   CString sReport;
   sReport.Format( "Successful synchronization!\n Time before: %02d:%02d:%02d.\n Time after: %02d:%02d:%02d.\n",
   dtOldTime.wHour, dtOldTime.wMinute, dtOldTime.wSecond, tmLocal.wHour, tmLocal.wMinute, tmLocal.wSecond);

   AfxMessageBox( sReport, MB_OK | MB_ICONINFORMATION );

   return;

}


Page : 1