in reply to NTP and perl

I wrote the following to make sure that localhost, using an ntp client/server combo (i.e. Tardis 2000), was synchronized to a remote ntp site. But it seems to work directly with the remote site as well. (If my memory serves me correctly, it uses SNTP.) No guarantees, of course! :-)
use IO::Socket; print GetNTPTime('ntp1.cs.wisc.edu'); sub GetNTPTime{ my $host = shift; my $timeout = 2; my $sock = IO::Socket::INET->new( Proto => 'udp', PeerPort => 123, PeerAddr => $host, Timeout => $timeout ) or do {warn "Can't contact $host\n"; return 0}; my $ntp_msg = pack("B8 C3 N11", '00100011', (0)x14); $sock->send($ntp_msg) or do {warn "Can't send NTP msg."; return 0} +; my $rin=''; vec($rin, fileno($sock), 1) = 1; select(my $rout=$rin, undef, my $eout=$rin, $timeout) or do {warn +"No answer from $host"; return 0}; $sock->recv($ntp_msg, length($ntp_msg)) or do {warn "Receive error from $host: ($!)"; return 0}; my ($LIVNMode, $Stratum, $Poll, $Precision, $RootDelay, $RootDispersion, $RefIdentifier, $Reference, $ReferenceF, $Original, $OriginalF, $Receive, $ReceiveF, $Transmit, $TransmitF ) = unpack('a C2 c1 N8 N N B32', $ntp_msg); $Receive -= 2208988800; my $NTPTime = $Receive + $ReceiveF / 65536 / 65536; $RefIdentifier = unpack('A4', $RefIdentifier); my $LI = vec($LIVNMode, 3, 2); my $VN = unpack("C", $LIVNMode & "\x38") >> 3; my $Mode = unpack("C", $LIVNMode & "\x07"); $sock->close; if ($RefIdentifier ne '1280') { return $NTPTime } else { return 0 } }
The value returned by GetNTPTime is in the same units as the Perl function time(). However, and note this carefully, it does NOT tell you what time it is. It only tells you what the server returned. Using this information to synchronize a local clock is a very complex process and not one appropriately undertaken by a Perl script.

If your really want to know what time it is, synchronized to an ntp server, get a good ntp client (e.g. ntpd for Linux or Tardis 2000 for Windows), let it do the dirty work, and just read the system clock.