基于NTP协议网络校时

先来个NTP协议介绍
http://blog.163.com/yzc_5001/blog/static/2061963420121283050787/

关于时间戳的换算工具
http://tool.chinaz.com/Tools/unixtime.aspx#

下面是代码,C-Free + MinGW 编译,须在工程连接参数里添加 -lwsock32


#include <stdio.h>
#include <time.h>
#include <winsock2.h>

#define JAN_1970 0x83AA7E80      /* 2208988800    1970-1900 in seconds*/

typedef union
{
    int  time;
    char time_array[4];
} Timestamp;

typedef struct 
{
    char message_hdr[16];//报文头部 
    char RefTimestamp[8];
    Timestamp T1;
    char T1_decimal[4]; //T1的小数部分 
    Timestamp T2;
    char T2_decimal[4]; //T2的小数部分 
    Timestamp T3;
    char T3_decimal[4]; //T3的小数部分 
} NTP_MESSAGE;

int main()
{
    WORD socketVersion = MAKEWORD(2,2);
    WSADATA wsaData; 
    if(WSAStartup(socketVersion, &wsaData) != 0)
    {
        return 0;
    }
    SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    SOCKADDR_IN sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(123);
    sin.sin_addr.S_un.S_addr = inet_addr("198.123.30.132");
    int len = sizeof(sin);
    
    char sendData[] = { //构造报文
    0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xAF, 0x5F, 0xF5, 0x23, 0xD7, 0x08, 0x00
    };
    
    printf("Connect to NTP Server...\n");
    
    time_t T1=time(NULL);
    
    sendto(sclient, sendData, sizeof(sendData), 0, (SOCKADDR *)&sin, len);

    char recvData[48]={0};
    int ret = recvfrom(sclient, recvData, 48, 0, (SOCKADDR *)&sin, &len);
    if(ret > 0)
    {
        time_t T4=time(NULL);
        
        printf("Connect success!\n\n");
        printf("Now the local time is %s",ctime(&T4));
        
        NTP_MESSAGE *ntp_time=(NTP_MESSAGE *)recvData;
        
        /* 大小端变换 由于NTP以1900为始,需变换 */
        ntp_time->T2.time=ntohl(ntp_time->T2.time)-JAN_1970;//T2
        ntp_time->T3.time=ntohl(ntp_time->T3.time)-JAN_1970;//T3
        
        /* NTP报文的网络延时=(T4-T1)-(T3-T2) */
        time_t net_delay=(T4-T1)-(ntp_time->T3.time-ntp_time->T2.time);
        printf("Net delay is %ld second(s).\n",net_delay);
        
        /* 误差补偿秒数=((T2-T1)+(T3-T4))/2 */
        time_t Deviation=(((time_t)ntp_time->T2.time-T1)+((time_t)ntp_time->T3.time-T4))/2;
        printf("\nThe deviation is %d second(s).\n",Deviation);
        
        if(Deviation != 0)
        {
            printf("Reset the local time...\n");
            
            time_t now=time(NULL)+Deviation;
            struct tm *ptr;
            ptr=localtime(&now);
            char buffer[20]={0};
            
            sprintf(buffer,"date %d-%d-%d",ptr->tm_year+1900,ptr->tm_mon+1,ptr->tm_mday);
            system(buffer);
            
            sprintf(buffer,"time %d:%d:%d",ptr->tm_hour,ptr->tm_min,ptr->tm_sec);
            system(buffer);
            now=time(NULL);
            printf("Now the local time is %s",ctime(&now));
        }
        else //没有误差,无需校时 
        {
            printf("Here is no need to set local time.\n");
        }
    }

    closesocket(sclient);
    WSACleanup();
    system("pause");
    return 0;
}

由于使用API 设置时间在 win7 下需要特殊的权限,故采用系统命令 date 和 time 设置,算是  不是办法的办法。
关于NTP协议,最开始给出的链接有具体的说明,在程序中,只需48个字节的必须内容即可,其它内容属可选项。

时间的小数部分抛弃不用,对于一般校时而言足够了。

下面给个截图



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鹏集成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值