界面效果

设置说明: 设置文件在软件目录下的 set.xml

  1.              cuuId 为当前选择的时间同步服务器ID 就是下面第几个item里的配置 (从零开始)

  2.   
          item 时间服务器列表项  
          name 时间服务器名称  
          ip   时间服务器地址 
          ip2  保留
  3.    后台服务时间同步方式 
              type 1 开机就同步 同步成功后停止服务 
                 2 开始服务后每隔STime分钟同步一次 
              STime   间隔的时间
  4.   日志记录方式
               level 2   记录程序运行生成的调试信息和错误信息
                   3    只记录程序运行产生的错误信息
                   4   不记录任何日志

**注 在界面上或者手动修改配置文件后要手动停止服务在启动服务

程序出来缘由: http://caipiao365.vip/article/12

程序源码: https://gitee.com/zuzong/Projects/tree/master/MyTime

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

 缘由 

 家里有两台老电脑,有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/exe/MyTime.zip

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

更多帮助: http://caipiao365.vip/article/MyTime

由于本人习惯用命令干活. 喜欢shell.在win下非常非常的不习惯他的 cmd和powershell   所以安装了 cygwin.   

cygwin的下载地址: http://www.cygwin.com/ 


然后在 vscode 下默认的 只有win的  cmd 或者 powershell  要是想在里面也可以用 cygwin 那么就要做点小小配置


具体配置文件如下

  "terminal.external.windowsExec": "E:\\cygwin64\\bin\\mintty.exe",

    "terminal.integrated.shell.windows": "E:\\cygwin64\\bin\\bash.exe"

    "terminal.integrated.shellArgs.windows": [

        "--login",

        "-i"

    ],



注意  E:\\cygwin64\\bin\\  把这个路径替换成你安装的路径就可以了


效果如下:


这些年隔三差五的有人问我或者让我推荐一些ssh工具. 由于本人忙(懒).就先记一下.下次还有人问就直接发链接了.


要是只是在win平台下用就推荐使用  MobaXterm

用过 XShell PuTT  SecureCRT  Termius 等这些,有好用的也有不好用的有要钱了有免费的.总之功能各有各的优势但是对我来说最好支持 ssh sftp 最基本的 要是能支持 rdp vnc这些就更好了.用过来用过去发现 MobaXterm功能非常强大,你可以用它来替换cmd,也支持SSH连接,插件也多支持好多的协议.个人用的话他的免费版够用了(可能是个人平时用习惯了linux特喜欢他的cmd)。界面如下

官网: https://mobaxterm.mobatek.net/


要是mac或者linux 推荐使用electerm当然win也可以用  主要支持ssh sftp(个人不喜欢打开多个软件) 标签分组的功能====发现里面好多功能挺实用的.界面如下:


官网: https://electerm.github.io/electerm/

习惯了linux的命令 然后在win下时不时的 输上了ls   clear 结果返回错误。然后自己又不想安装一在对的其他的环境。然后记得win下有一条命令是 doskey。可以给现有的命令取个别名。这个的话就方便多了

写一个小脚本 如下 保存成 doskey.cmd

@echo off
@doskey clear=cls $*
@doskey top=tasklist $*
@doskey ls=dir $*
@doskey mv=move $*
@doskey cp=copy $*
@doskey cat=type $*
@doskey pwd=echo %cd%
@doskey grep=findstr $*
@doskey ifconfig=ipconfig $*

要是还有其他的命令可以自己加



然后打开注册表

找到 HKEY_CURRENT_USER\Software\Microsoft\Command Processor这里

在这里下面 建立一个 名叫 AutoRun的字符串 值为上面脚本保存的路径,如下图


保存后在打开cmd就可以看效果了



希望对大家有用