Version 1 of Network Time Protocol - NTP

Updated 2002-05-23 13:27:01

Purpose - to discuss what NTP is, and to discuss coding issues relating to this protocol.

[hopefully one of my comrades in crime will fill in the blanks here as to RFC number, point to standard implementations of say an ntp daemon, etc.]

[Here's a start:-

Firstly, the protocol implemented in the code below is the "daytime" protocol, not NTP. The daytime protocol is described in RFC867 [L1 ].

NTP is a far more sophisticated protocol, version 3 of which is described in RFC1305, created by Dave Mills. More information including links to Dave Mills' implementation is available at http://www.ntp.org

Documentation and other links are at http://www.eecis.udel.edu/~ntp/documentation.html

NTP is implemented via UDP over port 123, and can operate in broadcast and multicast modes, or by direct queries.

--MNO ]

The following code was recently posted to comp.lang.tcl :

 ##
 ## good-time - for the correct time, ...
 ##
 ## Placed into the public domain by [email protected], January 1999.
 ##
 ## usage: good-time [host [port [timezone]]]
 ##     host - defaults to time.nist.gov.
 ##     port - defaults to 13.
 ##     timezone - defaults to nothing, not necessary for NIST format.
 ##
 ## After wading through a complicated linux time synchronization
 ## package, it turned out that the key was to telnet to time.nist.gov
 ## on port 13.  You can do that in tcl, so here it is.
 ##
 ## It also turns out that a lot of machines return some kind of time
 ## service on port 13, so I recognize a few variations in the format
 ## returned.
 ##
 ## See http://www.boulder.nist.gov/timefreq/ for more information and
 ## links to yet more information.
 ##
 # 23Jan02RT - add -set flag
 set doset 0
 if {$argc >= 1 && [string equal [lindex $argv 0] -set]} {
        incr argc -1
        set argv [lrange $argv 1 end]
        set doset 1
 }

 ##
 ## choose the host
 ##
        # 11Jan02RT TODO use host list
        # numeric values come from "Atomic Clock Sync v2.5" server menu
 set hlist {
        129.6.15.28         
        129.6.15.29         
        132.163.4.101       
        132.163.4.102       
        132.163.4.103       
        128.138.140.44      
        time-nw.nist.gov
        time-a.timefreq.bldrdoc.gov
        time.nist.gov
        allhoststried
 }
 # set host time.nist.gov
 if {$argc > 0} {
     set hlist [concat[lindex $argv 0] $hlist]
 }

 ##
 ## choose the port
 ##
 set port 13
 if {$argc > 1} {
     set port [lindex $argv 1];
 }

 ##
 ## choose the timezone
 ##
 set timezone {}
 if {$argc > 2} {
     set timezone [lindex $argv 2];
 }

 ##
 ## set a time out
 ##
 after [expr 30*1000] {
     close $sock
     puts stderr "timed out";
     if {[info exists lines]} {
        puts stderr "no time found in:\n$lines"
     }
     exit 1;
 }

 ##
 ## open a socket
 ##
 foreach h $hlist {
        if {[catch {socket $h $port} sock]} {
                #puts stderr "socket: $sock"
                #exit 2;
                puts stderr "host $h - FAILED"
                continue
        }
        break
 }

 ##
 ## read what comes back
 ##
 while {[gets $sock line] >= 0} {

     #
     # typical daytime response is unix date format without timezone indication
     #
     #  Mon Sep 16 21:59:22 1996
     #
     set seconds 0
     if {[regexp \
        {^... ([A-Z][a-z][a-z]) ([ \d]\d) (\d\d:\d\d:\d\d) (\d\d\d\d)$} \
         $line all month mday time year]} {
        set seconds [clock scan "$month $mday, $year $time $timezone"]
     }

     #
     # NIST time service format returned by:
     #
     #  time.nist.gov
     #  time-nw.nist.gov
     #  time-a.timefreq.bldrdoc.gov
     #
     # 50343 96-09-17 05:02:07 50 0 0  50.0 UTC(NIST) * 
     #
     if {!$seconds &&
       [regexp \
      {^..... (\d\d)-(\d\d)-(\d\d) (\d\d:\d\d:\d\d) .. . . ..... UTC\(NIST\)} \
      $line all year month day time]} {
        set seconds [clock scan "$month/$day/$year $time UTC"]
     }

     #
     # USNO master clock format returned by:
     #
     #  tick.usno.navy.mil
     #  tock.usno.navy.mil
     #
     # 50343 261 044932 UTC
     #
     if {!$seconds && [regexp {^..... ([ \d][ \d]\d) (\d\d)(\d\d)(\d\d) UTC$} \
             $line all doy hour minute second]} {
        set seconds [clock scan $hour:$minute:$second -gmt true]
     }
     if {$seconds} {
        puts "FETCHED: [clock format $seconds]"
        puts "  LOCAL: [clock format [clock seconds]]"
        if {$doset} {
            set newtime [clock format $seconds -format %H%M.%S]
            exec date.exe $newtime
            puts "set date to $newtime"
        }
        close $sock;
        exit 0;
    }

     #
     # save unrecognized stuff for final error message
     #
     append lines $line\n
 }

 ##
 ## give up
 ##
 close $sock;
 puts stderr "no time found in:\n$lines";
 exit 4

Category Acronym Category Internet Category Application