NTP is a pretty complex protocol. It's a lot more than just querying some other server for the correct time. I can't recall ever seeing any application software with built-in NTP client capabilities.
Are you just writing something that needs to know the correct time? Generally, to use NTP, you set up an NTP server on the local computer; the NTP server automatically keeps the system clock accurate, so other programs just have to query the system for the current time.
If you really need to query another host's clock directly from your perl module, check out Net::Time. It supports a couple of older network time protocols.
| [reply] |
Kludgy (at least for some values of kludgy), but you could
always run ntpdate via backticks or pipes and then
parse out the information it returns.
| [reply] |
NTP is complex and has a lot of authentication hooks you probably don't need.
SNTP (Simple Network Time Protocol) is a stripped-down version that's easy to implement. See RFC 2030.
The Time Protocol RFC 868 is probably better suited to your needs. It's so incredibly simple to implement, it's often one of the examples used in sockets programming tutorials.
| [reply] |
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. | [reply] [d/l] |
NTP has exactly one function - to keep the time on a computer correct with reference to other computers. It is much more than a communications protocol. It use some quite elaborate modelling to keep the time on the client synched with (very) high precision to the time on the server.
You could, at least in principle, rewrite the NTP programs in Perl, but this seems a little pointless. Perl is not a good langauge for doing lots of iterative calulations.
Have a look at the tutorial at http://www.eecis.udel.edu/~ntp/. Personally I think fletch is on the right track, if you need what I think you need.
--
Anthony Staines
| [reply] |