Synchronizing Your PC Clock Using HTTP Protocol

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

Introduction

The standard way to synchronize a PC’s clock though the Internet is by using a special Network Time Protocol (NTP). It was mainly developed at Delaware University in the United States. Tree versions of NTP were defined: the first in 1988, the second in 1989, and the third in 1992. The current version is the third, which is compatible with the previous ones. To make using NTP on personal computers easier, in 1995 the Simplified NTP (SNTP) was defined. Unfortunately, standard Windows software for versions Win95/98/Me/NT/W2KPro does not support synchronizing a PC clock through the Internet.

When I decided to create a synchronization program, I chose HTTP (Hypertext Transfer Protocol) instead of SNTP. I like it because it is more universal. All WWW pages that you watch are brought to your PC’s screen with this protocol. I created the program and called it “For Atomic Synchronization.”

There are a lot of government and scientific sites that show atomic time. There is a small delay in the site opening and receiving information. I explored my program “For Atomic Synchronization” for several months. The net delay seldom exceeds two seconds. I took half of the delay and corrected the time according to it. As result, I cannot find a difference between my PC clock’s time and the time that I watch on a TV screen or hear in an FM receiver.

As a time source, I use the Time Service Department of U.S. Naval Observatory’s site. It is the 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 work well but this one has a very simple format. The WWW page size is only 603 symbols (including the HTML tags). Try this URL, http://tycho.usno.navy.mil/cgi-bin/timer.pl,
and you will see the same information that my program gets.

The “For Atomic Synchronization” program is big enough that it deserves description. To demonstrate the main principles of synchronization, I created a small project that is described below.

Reading WWW Sites by Using the Windows 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 so forth. In this example, I use API functions instead of the same MFC classes because they are more universal and you can easily translate this code to VB or another programming language.

All API functions work as chains. The first function opens a Windows resource and returns its number that is named “handle”. Next, the function must use this handle. It could return another handle, return code, or something else. You must close the handle when you no longer need it.

Look at the function CBSAtomicEduDlg::OnSyncro (see code below). It works with the Internet as user:


  • Function InternetOpen opens the Internet connection. If you are offline now, it opens a Dialup connection window.

  • Function InternetOpenUrl retrieves the site that you are looking for.

  • Function InternetReadFile reads the site into the text buffer.

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

And do not forget to check for errors and close handles (function InternetCloseHandle). By using this program, you can explore any information on the Internet!

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

Universal and Local Time

My watch shows 02:00 am when it is midnight in London. The sun is rolling around the Earth, so there is different time in different places. (Note: I have heard about Copernicus and Jordano Bruno.) To define what time we use in the place where we are, we use a special time zone. Time zones are not strips on a globe. They were created not only according to geographical longitude but also according to states’ (countries’) delimiters too. If you want to use the Internet to synchronize your PC, you must have right time zone information in your operating system. You set it when you installed your OS; you can change it any time later.

If you know Universal time (GMT) and your time zone, you can easily calculate your local time.
Look at function LocalZoneTime (see code below). It calculates Universal time to Local time using time zone information. I got the Universal time from a Web site. I received all the information about time zones that I needed by calling the Win API function GetTimeZoneInformation. Look at Microsoft’s help to understand how to use this information. The information includes DST (daylight saving time) correction.

Links

http://www.brigsoft.com/bsatomic/ — This all-around synchronization site includes a 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 United States’ standard of time.

Source VC++ Code

It is a part of a dialog-based MFC project, which makes time synchronization.


// LocalZoneTime function — calculate Local time using Universal time.
// Time zone information is gotten from Windows using the
// GetTimeZoneInformation API function (see MSDN for more information).
// The function supports 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 is pressed.
// It opens an 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 Naval Observatory site.
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 the 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;
}

Downloads

Download file – 23 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read