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


Comments

  • Which Are THe Other Sites WithWhich U Have Tested The Code?

    Posted by IndrajeetK on 12/12/2008 07:56am

    Hello
    
    I Want To Know Which Are THE Other Sites With Which U  Have Tested Ur Code.
    
    Regards
    
    Indrajeet

    Reply
  • Regular expressions to the rescue!

    Posted by Legacy on 02/20/2004 12:00am

    Originally posted by: Daniel

    A nice modification to your program would be to use regular expressions (greta, boost::regexp, atl::regex) it would make the code more robust.

    All in All a good article

    Danderson

    Reply
  • Unrecognized communication error!

    Posted by Legacy on 07/16/2003 12:00am

    Originally posted by: miihhe

    Hi,
    
    

    I use your programm, but it always display "Unrecognized communication error!". The reason is "NumberOfBytesRead = 1000" always. Would you like to help me!

    Thanks.

    Helen

    Reply
  • URL open error!!!

    Posted by Legacy on 06/01/2003 12:00am

    Originally posted by: Himanshu

    hi Alex,
    u have used this URL for getting the time..http://tycho.usno.navy.mil/cgi-bin/timer.pl
    this is not opening either in IE and also the program says URL open error..I need to sort out this immediately..please help me out..what can be the problem..Thanks in advance..
    Himanshu

    Reply
  • Cool program

    Posted by Legacy on 05/09/2003 12:00am

    Originally posted by: LB

    I was looking for the way I can check the time from internet. Because I needed to release a demo program, and wanted to included some restriction in the program. By checking the time on the internet, this was done nicely.

    Thanks for the cool program.

    LB

    Reply
  • nice work... and one more idea

    Posted by Legacy on 05/27/2002 12:00am

    Originally posted by: mig

    what about using a ping signal to compute the average network latency ?

    Reply
  • PC Clock Synchronizing Using HTTP Protocol

    Posted by Legacy on 05/22/2002 12:00am

    Originally posted by: Gonzalo

    There is an error in the assumption of the size page:

    void CBSAtomicEduDlg::OnSyncro()
    {
    ...
    if(NumberOfBytesRead != 603)
    {
    AfxMessageBox( "Unrecognized communication error!", MB_OK | MB_ICONERROR );
    return;
    }
    /*
    NumberOfBytesRead == 615
    + buff {"<TITLE>What time is it?</TITLE>
    <H2> US Naval Observatory Master Clock time ... </H2>
    <H3>
    <B> May 22, 2002, 11:09:33 Universal Time
    <BR>
    <BR> May 22, 2002, 07:09:33 Eastern Daylight Time
    <BR> May 22, 2002, 06:09:33 Central "
    */
    ...
    }

    Perhaps you must read all the data and search in the string for the desired substring (i.e. Universal Time)?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • 10 Rules that Make or Break Enterprise App Development Projects In today's app-driven world, application development is a top priority. Even so, 68% of enterprise application delivery projects fail. Designing and building applications that pay for themselves and adapt to future needs is incredibly difficult. Executing one successful project is lucky, but making it a repeatable process and strategic advantage? That's where the money is. With help from our most experienced project leads and software engineers, …

  • Best-in-Class organizations execute on a strategy that supports the multi-channel nature of customer requests. These leading organizations do not just open up their service infrastructures to accommodate new channels, but also empower their teams to deliver an effective and consistent experience regardless of the channel selected by the customer. This document will highlight the key business capabilities that support a Best-in-Class customer engagement strategy.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds