时间同步助手


声明:本文转载自https://my.oschina.net/canye/blog/1633080,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

 缘由 

 家里有两台老电脑,有cmos电池没有电了,还有应该是BIOS出问题了.每次开机后时间恢复成了出厂时间.虽然不是什么大问题,但是也给使用时带来了很大的不方便.然后用win的时间同步服务一直更新不成功.折腾了好长时间(不知道为什么),估计是人长的丑的缘故吧^_^,有知道原因的麻烦告诉我.然后在网上找了一些时间同步的工具,发现不是有广告就是要手动去更新时间,然后就想这与其乱费长时间去试一个个的软件,还不如自己花点时间写一个. 就这样[时间同步小助手]就出来. 

事因

先不费话,来几张让人看了就上火的图片.因为平时用浏览器用的多.所以开机就喜欢打开chrome.结果出现下面这张可恶的图片.

然后打开服务一看,Windows Time服务是自动启动的 而且正在运行中.就这样我打一下面这个界面.

选择里面的服务器 点立即更新 都没法更新. 在这里自己输入时间服务器,结果也报错.没办法就来野蛮一点的打开注册表转到[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers]手动加时间服务器.然后重启在看里面有了但是还是更新出错.然后左百毒右谷歌,从比必到yandex. 搜到了一些大同小异的文章.然后高高兴兴的去按搜到的资料上的去做,结果我这台电脑居然不按套路出牌.

运行 w32tm  unregister

给我的回复是 

发生下列错误: 拒绝访问。 (0x80070005)

运行 w32tm  /debug /enable /file:......

给我的回复是 

发生下列错误: 拒绝访问。 (0x80070005)

反正执行 不管如何执行 w32tm的相关命令就给那一直不变的 友好的提示:发生下列错误: 拒绝访问。 (0x80070005)

 

然后就想着不想在折腾你了.没有那么多时间来折腾.去网上找时间同步的软件.下个一来丢盘即用就可以了.然后把时间更新了一下.打开chrom来搜 windows时间同步工具. 一看结果好多呀.然后又开始一个一个try.try. 结果大部分软件功能不好用,甚至还用不了.但是广告特别多.而且还绑定了好多的垃圾软件和流氓软件.应正了 安装5分钟,清理两小时.结果一个非常适合晒太阳的下午白白乱费了.然后我那暴躁的脾气上来了.想想宁愿去通宵几个晚上也要自己做一个时间同步小工具来用.说干就卷起袖子开干.

打开 bing   搜  rfc ntp  找到这份文档 https://tools.ietf.org/html/rfc958 

慢慢的啃完了他.定义了下面的通讯结构(主要看 Appendix A UDP Header Format )

struct NTPPacket {     union     {         struct _ControlWord         {             unsigned int uLI : 2;          // 00 = no leap, clock ok             unsigned int uVersion : 3;     // version 3 or version 4             unsigned int uMode : 3;        // 3 for client, 4 for server, etc.             unsigned int uStratum : 8;     // 0 is unspecified, 1 for primary reference system,             // 2 for next level, etc.             int nPoll : 8;                 // seconds as the nearest power of 2             int nPrecision : 8;            // seconds to the nearest power of 2         };          int nControlWord;                  // 4     };      int nRootDelay;                       // 4     int nRootDispersion;                  // 4     int nReferenceIdentifier;             // 4      __int64 n64ReferenceTimestamp;        // 8     __int64 n64OriginateTimestamp;        // 8     __int64 n64ReceiveTimestamp;          // 8      int nTransmitTimestampSeconds;       // 4     int nTransmitTimestampFractions;     // 4 };  /* 主要字段的解释如下:  l              LI(Leap Indicator):长度为2比特,值为“11”时表示告警状态,时钟未被同步。为其他值时NTP本身不做处理。  l              VN(Version Number):长度为3比特,表示NTP的版本号,目前的最新版本为3。  l              Mode:长度为3比特,表示NTP的工作模式。不同的值所表示的含义分别是:0未定义、1表示主动对等体模式、2表示被动对等体模式、3表示客户模式、4表示服务器模式、5表示广播模式或组播模式、6表示此报文为NTP控制报文、7预留给内部使用。  l              Stratum:系统时钟的层数,取值范围为1~16,它定义了时钟的准确度。层数为1的时钟准确度最高,准确度从1到16依次递减,层数为16的时钟处于未同步状态,不能作为参考时钟。  l              Poll:轮询时间,即两个连续NTP报文之间的时间间隔。  l              Precision:系统时钟的精度。  l              Root Delay:本地到主参考时钟源的往返时间。  l              Root Dispersion:系统时钟相对于主参考时钟的最大误差。  l              Reference Identifier:参考时钟源的标识。  l              Reference Timestamp:系统时钟最后一次被设定或更新的时间。  l              Originate Timestamp:NTP请求报文离开发送端时发送端的本地时间。  l              Receive Timestamp:NTP请求报文到达接收端时接收端的本地时间。  l              Transmit Timestamp:应答报文离开应答者时应答者的本地时间。  l              Authenticator:验证信息。  */

 

UDP通信的代码如下:

 

#define JAN_1970        0x83aa7e80 /* 1900年~1970年之间的时间秒数 */  bool TimeSockService::GetNetTime(const string strIP,UINT64 &uRetTime) {     SOCKET SendSocket;       sockaddr_in RecvAddr;       uRetTime = 0;     UString strError;      SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);      RecvAddr.sin_family = AF_INET;       RecvAddr.sin_port = htons(123);       HOSTENT* pHostent = gethostbyname(strIP.c_str());       if (pHostent != NULL)     {           RecvAddr.sin_addr.s_addr = *(u_long *)pHostent->h_addr_list[0];;       }else      {         strError.Format(L"error in gethostbyname: %d \r\n%s", WSAGetLastError(), sysErrorMsg().c_str());         LOG_ERR(strError.GetData());         if (_hWndGUI) SendMessage(_hWndGUI, WM_GET_NET_TIME_ERR, 0, LPARAM(strError.GetData()));          return false;       }        NTPPacket ntpSend = { 0 };     ntpSend.nControlWord = 0x1B;       NTPPacket ntpRecv;      int tv_out = 5000;      setsockopt(SendSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv_out, sizeof(tv_out));     sendto(SendSocket, (char*)&ntpSend, sizeof(ntpSend), 0, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));        sockaddr fromAddr = { 0 };       int nRead = sizeof(fromAddr);       if (SOCKET_ERROR != recvfrom(SendSocket, (char*)&ntpRecv, sizeof(ntpRecv), 0, &fromAddr, &nRead))       {          uRetTime = ntohl(ntpRecv.nTransmitTimestampSeconds) - JAN_1970;      }else     {           strError.Format(L"error in recvfrom: %d \r\n%s", WSAGetLastError(), sysErrorMsg().c_str());         LOG_ERR(strError.GetData());         if (_hWndGUI) SendMessage(_hWndGUI, WM_GET_NET_TIME_ERR, 0, LPARAM(strError.GetData()));     }     closesocket(SendSocket);     return true; }

然后封装成win的服务程序.为了方便管理做了个界面.具体效果如下:

设置成开机同步后运行后看的效果:

具体用法请点界面上的说明 按钮.欢迎使用找BUG.有什么问题欢迎在这里砸砖头^_^

程序下载地址: https://gitee.com/zuzong/Projects/raw/master/Mytime/MyTime.zip

 

个人博客地址:http://caipiao365.vip/article/12

本文发表于2018年03月11日 22:38
(c)注:本文转载自https://my.oschina.net/canye/blog/1633080,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2333 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1