我々の研究に関連する資料です

info_page
うるう秒とコンピュータクロック

日本標準時 2009年1月1日 8時59分59秒の直後にうるう秒が挿入されました。
このページでは、コンピュータクロックにおけるうるう秒対応関係の情報を紹介します。

うるう秒資料(PDF)
Perl版SNTPサーバ ベースバージョン
Perl版SNTPサーバ うるう秒テスト用バージョン

Perl版SNTPサーバ ベースバージョン 2005.12.01


NTP / SNTP クライアントの動作検証を行う場合、サーバの挙動を変更する必要が生ずることがあります。
このような場合には、短くて変更を加えやすい「簡易サーバ」を使うと便利でしょう。
以下に Perl で書かれたサンプルを示します。

-------------------------------------------------------------------------
#!/usr/bin/perl -wT

use strict;
use Socket;
use Time::HiRes qw( gettimeofday );

my $proto = getprotobyname('udp');
socket(NTP, PF_INET, SOCK_DGRAM, $proto)        or die "socket: $!";
my $paddr = sockaddr_in( 123, INADDR_ANY );
bind(NTP, $paddr)                               or die "bind: $!";

my ( $rb, $sb, $vn, $client, $seconds, $microsec );
$sb = "\0" x 48;

while ("You love NTP") {
        ($client = recv(NTP, $rb, 256, 0)) or next;
        ( length($rb) >= 48 ) or next;
        ($seconds, $microsec) = gettimeofday;
        $vn = unpack("N", substr($rb, 0, 4)) & 0x38000000;
        substr($sb, 0, 4) = pack("N", 0x040106F0 | $vn );       # flag
        substr($sb, 4, 4) = pack("N", 0);                       # delay
        substr($sb, 8, 4) = pack("N", 0x00000010);              # dispersion
        substr($sb,12, 4) = "LOCL";                             # Ref ID

        substr($sb,16, 4) = pack("N", $seconds + 0x83AA7E80);
        substr($sb,20, 4) = pack("N", 0 );
        substr($sb,24, 8) = substr($rb,40, 8);
        substr($sb,32, 4) = pack("N", $seconds + 0x83AA7E80);
        substr($sb,36, 4) = pack("N", ($microsec/500000) * 0x80000000 );
        ($seconds, $microsec) = gettimeofday;
        substr($sb,40, 4) = pack("N", $seconds + 0x83AA7E80);
        substr($sb,44, 4) = pack("N", ($microsec/500000) * 0x80000000 );

        send(NTP, $sb, 0, $client);
}

Perl版SNTPサーバ うるう秒テスト用バージョン 2005.12.01


$NTP_LI : 05/12/31 00:00:00 UTC 以降、うるう秒挿入終了まで、LI=1 になります
$NTP_LEAP : 06/01/01 00:00:00 UTC の直前にうるう秒が挿入されます
$USO_LEAP : うるう秒挿入が 05/12/11 00:00:00 UTC に起こるよう時刻にオフセットをかけます

-------------------------------------------------------------------------
#!/usr/bin/perl -wT

use strict;
use Socket;
use Time::HiRes qw( gettimeofday );
use Time::Local;

my ( $rb, $sb, $vn, $client, $sec, $msec, $proto, $paddr );
my ( $NTP_LI, $NTP_LEAP, $MODE, $FLAG, $STR, $POLL, $PREC );
my ( $USO_LEAP, $USO_OFFSET );

$NTP_LI = timegm( 0, 0, 0, 31, 12-1, 05 );      # 05/12/31 00:00:00 UTC
$NTP_LEAP = timegm( 0, 0, 0, 1, 1-1, 06 );      # 06/01/01 00:00:00 UTC

$USO_LEAP = timegm( 0, 0, 0, 11, 12-1, 05 );    # 05/12/11 00:00:00 UTC
$USO_OFFSET = $NTP_LEAP - $USO_LEAP;

$MODE = 4;              # mode = 4 (server)
$STR = 1;               # stratum 1
$POLL = 6;              # poll interval = 2^6 sec
$PREC = -16;            # precision = 2^-16 sec

$proto = getprotobyname('udp');
socket(NTP, PF_INET, SOCK_DGRAM, $proto)        or die "socket: $!";
$paddr = sockaddr_in( 123, INADDR_ANY );
bind(NTP, $paddr)                               or die "bind: $!";

$sb = "\0" x 48;

while ("You hate leapseconds") {
        ($client = recv(NTP, $rb, 256, 0)) or next;
        ( length($rb) >= 48 ) or next;
        ($sec, $msec) = gettimeofday;
        $sec += $USO_OFFSET;
        $FLAG = $MODE | ( unpack("C",substr($rb,0,1)) & 0x38 ); # version
        if(($sec >= $NTP_LI) && ($sec <= $NTP_LEAP)) { $FLAG |= 0x40; }
        if(($sec > $NTP_LEAP)) { $sec -= 1; }           # offset
        substr($sb, 0, 4) = pack("CCCc", $FLAG, $STR, $POLL, $PREC);
        substr($sb, 4, 4) = pack("N", 0);               # delay
        substr($sb, 8, 4) = pack("N", 0);               # dispersion
        substr($sb,12, 4) = "LOCL";                     # Ref ID
        substr($sb,16, 4) = pack("N", $sec + 0x83AA7E80);
        substr($sb,20, 4) = pack("N", 0 );
        substr($sb,24, 8) = substr($rb,40, 8);
        substr($sb,32, 4) = pack("N", $sec + 0x83AA7E80);
        substr($sb,36, 4) = pack("N", ($msec/500000) * 0x80000000 );
        ($sec, $msec) = gettimeofday;
        $sec += $USO_OFFSET;
        if(($sec > $NTP_LEAP)) { $sec -= 1; }
        substr($sb,40, 4) = pack("N", $sec + 0x83AA7E80);
        substr($sb,44, 4) = pack("N", ($msec/500000) * 0x80000000 );

        send(NTP, $sb, 0, $client);
}


Page Top



この改行は必要→