本帖最后由 iamlimeng 于 2019-08-11 19:51 編輯
最近在校準(zhǔn)家里的時(shí)鐘,找了不少工具,獲得的時(shí)間都不太精確,還是自己寫吧。很久以前寫過一個(gè),由于算法問題,精度不夠高,重寫了算法,現(xiàn)在精度應(yīng)該在0.1秒以內(nèi)(前提是服務(wù)器時(shí)間精確)。
目前國內(nèi)比較可靠,網(wǎng)絡(luò)訪問延時(shí)少的授時(shí)服務(wù)器有:阿里云授時(shí)服務(wù)器、國家授時(shí)中心服務(wù)器、NTP.ORG,當(dāng)然蘋果和微軟的授時(shí)服務(wù)器也不錯(cuò)。
NTP(Network Time Protocol)網(wǎng)絡(luò)時(shí)間協(xié)議基于UDP,用于網(wǎng)絡(luò)時(shí)間同步的協(xié)議,使網(wǎng)絡(luò)中的計(jì)算機(jī)時(shí)鐘同步到UTC,再配合各個(gè)時(shí)區(qū)的偏移調(diào)整就能實(shí)現(xiàn)精準(zhǔn)同步對時(shí)功能。NTP授時(shí)精度與NTP服務(wù)器與用戶間的網(wǎng)絡(luò)狀況有關(guān):廣域網(wǎng)授時(shí)精度通常能達(dá)50ms級,但有時(shí)超過500ms;局域網(wǎng)授時(shí)不存在路由器路徑延遲問題,因而授時(shí)精度理論上可以提到亞毫秒級;但是Windows內(nèi)置NTP服務(wù),在局域網(wǎng)內(nèi)其最高授時(shí)精度也只能達(dá)10ms級。
IETF的RFC5905對NTP數(shù)據(jù)包的結(jié)構(gòu)有詳細(xì)說明。
萬能的Perl就有效率比較高的解析模塊Net::NTP,結(jié)合RFC5905文檔的說明,將NTP服務(wù)器反饋的數(shù)據(jù)包解析后,只須對接收到的時(shí)間數(shù)據(jù)進(jìn)行延時(shí)修正,就能獲得準(zhǔn)確的時(shí)間,這個(gè)精度對于一般用途足夠了。
代碼分享如下: - #!/usr/bin/perl
- =info
- Author: iamlimeng
- Date:2019-08
- =cut
- use strict;
- use warnings;
- use Net::NTP qw(get_ntp_response);
- $| = 1;
- my $interval = 0.999999;
- my $NTP_Server = 'ntp1.aliyun.com'; #阿里云授時(shí)服務(wù)器,可靠性高
- #my $NTP_Server = 'ntp.aliyun.com'; #阿里云授時(shí)服務(wù)器,可靠性高
- #my $NTP_Server = 'ntp.ntsc.ac.cn'; #國家授時(shí)中心,可靠性高
- #my $NTP_Server = 'cn.ntp.org.cn';
- print "NTP Server: $NTP_Server\n\n";;
- my %response = eval { get_ntp_response($NTP_Server) };
- if (%response) {
- my $time = $response{'Transmit Timestamp'} + $response{'Delay'}/2;
- my ($now,$wait) = split(/\./,$time);
- select(undef, undef, undef, 1-$wait/100000);
- while(1) {
- $now++;
- print "\r",time_from_utc($now);
- select(undef, undef, undef, $interval);
- }
- }
- else { print "Connect NTP Server Faild!"; }
- <STDIN>;
- exit;
- sub time_from_utc {
- my $utc = shift;
- my ($sec,$min,$hour,$day,$mon,$year,$weekday,$yeardate,$savinglightday) = (localtime($utc));
- return (sprintf("%04d.%02d.%02d %02d:%02d:%02d",$year+1900,$mon+1,$day,$hour,$min,$sec));
- }
復(fù)制代碼
|