免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 42959 | 回复: 8
打印 上一主题 下一主题

从NTP授时服务器获取高精度时间 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2019-08-11 19:49 |只看该作者 |倒序浏览
本帖最后由 iamlimeng 于 2019-08-11 19:51 编辑

最近在校准家里的时钟,找了不少工具,获得的时间都不太精确,还是自己写吧。很久以前写过一个,由于算法问题,精度不够高,重写了算法,现在精度应该在0.1秒以内(前提是服务器时间精确)。

目前国内比较可靠,网络访问延时少的授时服务器有:阿里云授时服务器、国家授时中心服务器、NTP.ORG,当然苹果和微软的授时服务器也不错。

NTP(Network Time Protocol)网络时间协议基于UDP,用于网络时间同步的协议,使网络中的计算机时钟同步到UTC,再配合各个时区的偏移调整就能实现精准同步对时功能。NTP授时精度与NTP服务器与用户间的网络状况有关:广域网授时精度通常能达50ms级,但有时超过500ms;局域网授时不存在路由器路径延迟问题,因而授时精度理论上可以提到亚毫秒级;但是Windows内置NTP服务,在局域网内其最高授时精度也只能达10ms级。

IETF的RFC5905对NTP数据包的结构有详细说明。

万能的Perl就有效率比较高的解析模块Net::NTP,结合RFC5905文档的说明,将NTP服务器反馈的数据包解析后,只须对接收到的时间数据进行延时修正,就能获得准确的时间,这个精度对于一般用途足够了。

代码分享如下:
  1. #!/usr/bin/perl

  2. =info
  3.     Author: iamlimeng
  4.     Date:2019-08
  5. =cut

  6. use strict;
  7. use warnings;
  8. use Net::NTP qw(get_ntp_response);

  9. $| = 1;
  10. my $interval = 0.999999;

  11. my $NTP_Server = 'ntp1.aliyun.com'; #阿里云授时服务器,可靠性高
  12. #my $NTP_Server = 'ntp.aliyun.com'; #阿里云授时服务器,可靠性高
  13. #my $NTP_Server = 'ntp.ntsc.ac.cn';  #国家授时中心,可靠性高
  14. #my $NTP_Server = 'cn.ntp.org.cn';

  15. print "NTP Server: $NTP_Server\n\n";;
  16. my %response = eval { get_ntp_response($NTP_Server) };
  17. if (%response) {
  18.         my $time = $response{'Transmit Timestamp'} + $response{'Delay'}/2;
  19.         my ($now,$wait) = split(/\./,$time);
  20.         select(undef, undef, undef, 1-$wait/100000);
  21.          while(1) {
  22.                  $now++;
  23.                  print "\r",time_from_utc($now);
  24.                  select(undef, undef, undef, $interval);
  25.            }
  26. }
  27. else { print "Connect NTP Server Faild!"; }

  28. <STDIN>;
  29. exit;

  30. sub time_from_utc {
  31.         my $utc = shift;
  32.         my ($sec,$min,$hour,$day,$mon,$year,$weekday,$yeardate,$savinglightday) = (localtime($utc));
  33.          return (sprintf("%04d.%02d.%02d %02d:%02d:%02d",$year+1900,$mon+1,$day,$hour,$min,$sec));
  34. }
复制代码

评分

参与人数 1信誉积分 +20 收起 理由
523066680 + 20 感谢分享

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2019-08-13 11:47 |只看该作者
搞了一个成品:
链接:https://pan.baidu.com/s/1zXd9iJ2CaphRPloJ6VZ4dw
提取码:a3qj

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
3 [报告]
发表于 2019-08-13 12:41 |只看该作者
你用哪个模块做GUI, Label 更新的时候有点闪烁

论坛徽章:
0
4 [报告]
发表于 2019-08-13 12:54 |只看该作者
Win32::GUI,写GUI很麻烦,简单的搞一搞勉强可以。Label更新是个Timer,确实有点闪烁。

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
5 [报告]
发表于 2019-08-13 15:13 |只看该作者
本帖最后由 523066680 于 2019-08-13 15:16 编辑
iamlimeng 发表于 2019-08-13 12:54
Win32::GUI,写GUI很麻烦,简单的搞一搞勉强可以。Label更新是个Timer,确实有点闪烁。

我现在用 IUP,和 WIN32::GUI 应该是同一个作者,kmx
https://metacpan.org/author/KMX

记得 Win32::GUI 有些模块不能用了,IUP还算稳定,但打包成exe没试过 (总之就是各种不方便啊)

这几天用IUP做的一个电商发货辅助工具



论坛徽章:
0
6 [报告]
发表于 2019-08-13 15:53 |只看该作者
ActiveState在ActivePerl-5.22.2.2202的PPM中没有提供编译好的IUP安装包,而这个版本是PDK支持的最后一个版本,我用CPAN安装IUP未成功,所以打包有可能没戏。

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
7 [报告]
发表于 2019-08-13 19:18 |只看该作者
本帖最后由 523066680 于 2019-08-13 19:20 编辑

IUP的(只有外壳),写起来应该和 WIN32:GUI差不多。我用的 Strawberry Perl 5.24 32位
  1. use utf8;
  2. use IUP ':all';
  3. use Date::Format;
  4. use Time::HiRes qw/gettimeofday/;
  5. STDOUT->autoflush(1);

  6. my $label1 = IUP::Label->new(
  7.     TITLE => "",
  8.     FONT => "Microsoft YaHei",
  9.     FONTSIZE=>"18",
  10.     EXPAND => "HORIZONTAL",
  11. );

  12. my $label2 = IUP::Label->new(
  13.     TITLE => "",
  14.     FONT => "Microsoft YaHei",
  15.     FONTSIZE=>"18",
  16.     EXPAND => "HORIZONTAL",
  17. );

  18. my $dlg = IUP::Dialog->new(
  19.     child => IUP::Vbox->new( child => [$label1, $label2] ),
  20.     TITLE => "IupTimer",
  21.     SIZE  => "300x100",
  22. );

  23. $timer1 = IUP::Timer->new(
  24.         TIME => "100",
  25.         RUN => "YES",
  26.         ACTION_CB => sub {
  27.             my $msec = sprintf "%03d", int((gettimeofday)[1]/1000);
  28.             $label1->TITLE( time2str("%c ", time()) .$msec );
  29.         }
  30.     );

  31. $timer2 = IUP::Timer->new(
  32.         TIME => "200",
  33.         RUN => "YES",
  34.         ACTION_CB => sub {
  35.             my $msec = sprintf "%03d", int((gettimeofday)[1]/1000);
  36.             $label2->TITLE( time2str("%c ", time()) .$msec );
  37.         }
  38.     );

  39. $dlg->Show();

  40. IUP->MainLoop;
复制代码

论坛徽章:
0
8 [报告]
发表于 2019-08-14 08:43 |只看该作者
回复 7# 523066680

我昨天试了ActivePerl 5.26,PPM库中有IUP,安装很容易,你的代码也测试了,看起来非常好。PDK最高只支持到5.22,所以IUP代码打包估计是难了。

论坛徽章:
0
9 [报告]
发表于 2020-04-21 16:56 |只看该作者
膜拜大神了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP