NTP服务器

2023-05-16

1、NTP服务器

  NTP协议是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机的时间的协议。它的用途是把计算机的时钟同步到世界协调时UTC,其精度在局域网内可达0.1ms,在互联网上绝大多数的地方其精度可以达到1-50ms。它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。时间按NTP服务器的等级传播。按照离外部UTC源的远近把所有服务器归入不同的Stratum(层)中。

  NTP要提供准确的时间,就必须有准确的时间来源,那可以用格林尼治时间吗?答案是否定的。因为格林尼治时间是以地球自转为基础的时间计量系统,但是地球每天的自转是有些不规则的,而且正在缓慢加速,因此,格林尼治时间已经不再被作为标准时间使用。

  新的标准时间,是由原子钟报时的国际标准时间UTC(Universal Time Coordinated,世界协调时)。所以NTP获得UTC的时间来源可以是原子钟、天文台、卫星,也可以从Internet上获取。

  有了准确而可靠的的时间源,那这个时间如何传播呢?

  NTP提供准确时间,首先要有准确的时间来源,这一时间应该是国际标准时间UTC。 NTP获得UTC的时间来源可以是原子钟、天文台、卫星,也可以从Internet上获取。这样就有了准确而可靠的时间源。在NTP中,定义了时间按照服务器的等级传播,按照离外部UTC源远近将所有的服务器归入不同的Stratum(层)中,时间按NTP服务器的等级传播。按照离外部UTC 源的远近将所有服务器归入不同的Stratum(层)中。Stratum-1在顶层,有外部UTC接入,而Stratum-2则从Stratum-1获取时间,Stratum-3从Stratum-2获取时间,以此类推,但Stratum层的总数限制在15以内。所有这些服务器在逻辑上形成阶梯式的架构相互连接,而Stratum-1的时间服务器是整个系统的基础。

  计算机主机一般同多个时间服务器连接, 利用统计学的算法过滤来自不同服务器的时间,以选择最佳的路径和来源来校正主机时间。即使主机在长时间无法与某一时间服务器相联系的情况下,NTP服务依然有效运转。

  为防止对时间服务器的恶意破坏,NTP使用了识别(Authentication)机制,检查来对时的信息是否是真正来自所宣称的服务器并检查资料的返回路径,以提供对抗干扰的保护机制。

2、UTC

  协调世界时,即格林威治平太阳时间,又称世界统一时间、世界标准时间、国际协调时间。由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。

  协调世界时是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。中国大陆采用ISO 8601-1988的《数据元和交换格式信息交换日期和时间表示法》(GB/T 7408-1994)称之为国际协调时间,代替原来的GB/T 7408-1994;中国台湾采用CNS 7648的《资料元及交换格式–资讯交换–日期及时间的表示法》,称之为世界统一时间。

  这套时间系统被应用于许多互联网和万维网的标准中,例如,网络时间协议就是协调世界时在互联网中使用的一种方式。

  GMT(Greenwich Mean Time,格林威治时间)是英国格林尼治当地时间,它和UTC是的时间是一样的,及GMT=UTC+0。

  在军事中,协调世界时区会使用“Z”来表示。又由于Z在无线电联络中使用“Zulu”作代称,协调世界时也会被称为"Zulu time"。中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。

3、NTP报文格式

  NTP是从时间协议(Time Protocol)和ICMP时间戳报文(ICMP TimeStamp Message)演变而来,在准确性和健壮性方面进行了特殊的设计,理论上精度可达十亿分之一秒。

  NTP协议应用于分布式时间服务器和客户端之间,实现客户端和服务器的时间同步,从而使网络内所有设备的时钟基本保持一致。

  NTP协议是基于UDP进行传输的,使用端口号为123。

            图1 NTP数据报文格式 

字段名长度含义
LI(Leap Indicator)2比特这是一个两位的代码,表示在NTP时间标尺中将要插入的下一跳情况。值为“11”时表示告警状态,时钟不能被同步。
VN(Version Number)3比特NTP的版本号。
Mode3比特

NTP的工作模式。不同值表示的含义如下:

0:reserved,保留。

1:symmetric active,主动对等体模式。

2:symmetric passive,被动对等体模式。

3:client,客户模式。

4:server,服务器模式。

5:broadcast,广播模式。

6:reserved for NTP control messages,NTP控制报文。

7:reserved for private use,内部使用预留。

Stratum8比特时钟的层数,定义了时钟的准确度。层数为1的时钟准确度最高,从1到15依次递减。
Poll Interval8比特轮询时间,即发送报文的最小间隔时间。
Precision8比特时钟的精度。
Root Delay32比特到主参考时钟的总往返延迟时间。
Root Dispersion32比特本地时钟相对于主参考时钟的最大误差。
Reference Identifier32比特标识特定参考时钟。
Reference Timestamp64比特本地时钟最后一次被设定或更新的时间。如果值为0表示本地时钟从未被同步过。
Originate Timestamp64比特NTP报文离开源端时的本地时间。
Receive Timestamp64比特NTP报文到达目的端的本地时间。
Transmit Timestamp64比特目的端应答报文离开服务器端的本地时间。
Authenticator96比特(可选)验证信息。

                          

            图2 NTP控制报文格式 

字段名长度含义
02比特保留位。NTP本身不做处理。
VN(Version Number)3比特NTP的版本号,目前值为3。
63比特表明是控制报文。
REM3比特

R:0表示命令,1表示响应。

E:0表示发送正常响应,1表示发送错误响应。

M:0表示最后一个分片,1表示其他。

Op5比特操作码,表明命令的类型。
Sequence16比特发送或接受到报文的顺序号。
Status16比特表明当前系统的状态。
Association ID16比特连接标示。
Offset16比特偏移量。
Count16比特数据域的长度。
Data最大468比特包括发送报文或接受报文中的数据信息。
Padding16比特填充字段。
Authenticator96比特(可选)验证信息。

2、访问NTP服务器

//NTP的端口号
NTP_PORT                    123    


//常见的NTP的IP地址
uint8_t ntp_server_ip[4]={103,11,143,248};        //新加坡
uint8_t ntp_server_ip[4]={133,243,238,243};       //日本东京
uint8_t ntp_server_ip[4]={85,199,214,100};        //英国
uint8_t ntp_server_ip[4] = {202,120,2,101};       //上海交通大学ntp服务器IP地址202.120.2.101
uint8_t ntp_server_ip[4] = {210,72,145,44};       //国家授时中心服务器IP地址    210,72,145,44
uint8_t ntp_server_ip[4] = {202,118,1,81};        //辽宁省沈阳市 教育网
uint8_t ntp_server_ip[4]={203,107,6,88};          //阿里云
uint8_t ntp_server_ip[4]={120,25,115,20};         //阿里云
uint8_t ntp_server_ip[4]={120,25,108,11};         //阿里云
//报文结构体
typedef struct NTP_MessageTypeDef
{
    unsigned int        leap                : 2;/* leap indicator */
    unsigned int        version             : 3;/* version number       ntp版本号*/
    unsigned int        mode                : 3;/* mode                 ntp工作模式*/
    unsigned int        stratum             : 8;/* stratum              时钟层数*/
    unsigned int        poll                : 8;/* poll interval        轮询时间*/
    unsigned int        precision           : 8;/* precision            时钟的精度*/
    unsigned int        rootdelay;              /* root delay           到主参考时钟的总往返延迟时间*/
    unsigned int        rootdisp;               /* root dispersion      本地时钟相对于主参考时钟的最大误差*/
    unsigned int        refid;                  /* reference ID         标识特定参考时钟*/
    unsigned long long  reftime;                /* reference time       本地时钟最后一次被设定或更新的时间*/
    unsigned long long  oritime;                /* origin timestamp     NTP报文离开源端时的本地时间*/
    unsigned long long  rectime;                /* receive timestamp    NTP报文到达目的端的本地时间*/
    unsigned long long  tratime;                /* transmit timestamp   目的端应答报文离开服务器端的本地时间*/
    unsigned int        Authenticator[3];        /* Authenticator       (可选)验证信息 */
} NTP_MessageTypeDef;
Leap Indicator(LI) :闰秒指示符,这是一个2位的代码,用于警示在当天的最后一分钟里插入或删除的闰秒。取值如下:
  0:无预告
  1:最近一分钟有61秒   
  2:最近一分钟有59秒   
  3:警告状态(时钟未同步)

Version Number(VN) :版本号,这是一个3位的整数,用于表示NTP的版本。

Mode :模式,这是一个3位的整数,表示模式,值定义如下:
  0:保留
  1:对称主动
  2:对称被动
  3:客户端
  4:服务器端
  5:广播
  6:为NTP控制控制消息
  7:为自用保留

Stratum :本地时钟层级,这是一个八位无符号整数,表示本地时钟的层级,其值定义如下:
  0:未定义或难以获得
  1:主要参考(如无线电时钟钟,校正的院子时钟)
  2-255:第二参考(通过NTP或SNTP)

Poll :轮询间隔,这是一个8位有符号整数,用于表示连续消息之间的最大间隔,以最接近2的N次幂来表示。如值为6表示2^6=64。

Precision :本地时钟精度精度,这是一个8位有符号整数,用于表示本地时钟精度,以最接近2的N次幂来表示。

Root Delay :这是一个32位有符号定点数,表示主要参考源的总往返时延,以秒为单位。该变量可以为正值和负值,具体取决于时间精度和偏移。

Root Dispersion :这是一个32位有符号定点数,表示相对于主参考源的最大误差,以秒为单位,在15和16位之间。通常在该字段中出现的值范围为0到几百毫秒

Reference Identifier :这是一个标识特定参考源的32位位串。在NTP版本3或版本4层级0或层级1服务器的情况下,这是一个4字符ASCII字符串,左对齐并且以0填充到32位。在NTP版本3辅助服务器中,这是参考源的32位IPv4地址。

Reference Timestamp :这是以64位时间戳格式表示的上次设置或更正的本地时钟时间。

Original Timestamp :这是以64位时间戳格式表示的请求离开客户端的时间。

Receive Timestamp :这是以64位时间戳格式表示的请求到达服务器端的时间。

Transmit Timestamp :这是以64位时间戳格式表示的应答离开服务器端的时间。

Authentication :认证信息。

  

 测试程序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>

#pragma comment(lib,"ws2_32.lib")



typedef unsigned char            uint8_t;
typedef unsigned short int        uint16_t;
typedef unsigned int            uint32_t;



#define NTP_PORT                    123                        //NTP的端口


#define SECS_PERDAY                    86400UL                 // 一天的秒数 day = 60*60*24
#define NTP_START_TIME_YEAR            1900                //微软的时间戳是从1900.1.1算起,而unix的时间戳是从1970.1.1算起
#define FOUR_YEAR_DAYS                 (366+365+365+365)    //4年一个周期内的总天数(NTP_START_TIME_YEAR~2038不存在2100这类年份,故暂不优化)1900开始:(366+365+365+365),但是1900不是闰年,计算完后要加1天  1970开始:(365+365+366+365)




#define BUFFER_SIZE                    1024    //缓冲区大小




//NTP服务器报文
typedef struct NTP_MessageTypeDef
{
    unsigned int        leap : 2;/* leap indicator */
    unsigned int        version : 3;/* version number          ntp版本号*/
    unsigned int        mode : 3;/* mode                 ntp工作模式*/
    unsigned int        stratum : 8;/* stratum              时钟层数*/
    unsigned int        poll : 8;/* poll interval        轮询时间*/
    unsigned int        precision : 8;/* precision            时钟的精度*/
    unsigned int        rootdelay;              /* root delay            到主参考时钟的总往返延迟时间*/
    unsigned int        rootdisp;               /* root dispersion        本地时钟相对于主参考时钟的最大误差*/
    unsigned int        refid;                  /* reference ID            标识特定参考时钟*/
    unsigned long long  reftime;                /* reference time        本地时钟最后一次被设定或更新的时间*/
    unsigned long long  oritime;                /* origin timestamp        NTP报文离开源端时的本地时间*/
    unsigned long long  rectime;                /* receive timestamp    NTP报文到达目的端的本地时间*/
    unsigned long long  tratime;                /* transmit timestamp    目的端应答报文离开服务器端的本地时间*/
    unsigned int        Authenticator[3];        /* Authenticator           (可选)验证信息 */
} NTP_MessageTypeDef;





typedef struct NTP_TimeTypeDef
{
    uint16_t year;        //年
    uint8_t  month;        //月
    uint8_t  date;        //日
    uint8_t  week;        //星期
    uint8_t     hour;        //小时
    uint8_t  minute;    //分钟
    uint8_t  second;    //秒钟

    unsigned long long time_s;    //秒时间
}NTP_TimeTypeDef;
#include "ntp.h"


static uint8_t peace_month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };//平年每个月的天数
static uint8_t leap_month_days[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //闰年每个月的天数


/************************************************************************************************
* @ 函 数 名:NTP_GenerateReqMessage
* @ 功能说明:生成NTP服务器请求报文
* @ 参    数:p_Message_Buf:报文缓冲区
* @ 返 回 值:无
************************************************************************************************/
static void NTP_GenerateReqMessage(uint8_t *p_Message_Buf)
{
    NTP_MessageTypeDef NTP_MessageStruct;

    NTP_MessageStruct.leap = 0;
    NTP_MessageStruct.version = 4;
    NTP_MessageStruct.mode = 3;
    NTP_MessageStruct.stratum = 0;
    NTP_MessageStruct.poll = 0;
    NTP_MessageStruct.precision = 0;
    NTP_MessageStruct.rootdelay = 0;
    NTP_MessageStruct.rootdisp = 0;
    NTP_MessageStruct.refid = 0;
    NTP_MessageStruct.reftime = 0;
    NTP_MessageStruct.oritime = 0;
    NTP_MessageStruct.rectime = 0;
    NTP_MessageStruct.tratime = 1;
    NTP_MessageStruct.Authenticator[0] = 0;
    NTP_MessageStruct.Authenticator[1] = 0;
    NTP_MessageStruct.Authenticator[2] = 0;


    //memcpy((void *)p_Message_Buf, (void const*)(&NTP_MessageStruct), sizeof(NTP_MessageStruct));

    uint8_t temp = 0;
    temp = (NTP_MessageStruct.leap << 6) + (NTP_MessageStruct.version << 3) + (NTP_MessageStruct.mode);

    p_Message_Buf[0] = 0x23;  // 0x23 = NTP_MessageStruct.leap << 6 + NTP_MessageStruct.version << 3 + NTP_MessageStruct.mode    

    return;
}







/************************************************************************************************
* @ 函 数 名:NTP_WeekCalculate
* @ 功能说明:根据日期计算星期
* @ 参    数:p_NTP_TimeStruct:时间结构体
* @ 返 回 值:无
************************************************************************************************/
static uint8_t NTP_WeekCalculate(NTP_TimeTypeDef *p_NTP_TimeStruct)
{
    uint16_t year = 0;
    uint8_t month = 0;
    uint8_t date = 0;
    uint8_t week = 0;

    year = p_NTP_TimeStruct->year;
    month = p_NTP_TimeStruct->month;
    date = p_NTP_TimeStruct->date;


    if (month == 1 || month == 2)
    {
        month += 12;
        year--;
    }

    week = (date + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7;

    return (week + 1);
}





/************************************************************************************************
* @ 函 数 名:NTP_Leapyearjudgment
* @ 功能说明:判断是否是闰年
* @ 参    数:Year:年
* @ 返 回 值:0: 平年    1:闰年
************************************************************************************************/
static uint8_t NTP_Leapyearjudgment(uint16_t Year)
{
    uint8_t ret = 0;

    if (Year % 400 == 0)//能被400整除的就是闰年
    {
        ret = 1;
    }
    else
    {
        if (Year % 4 == 0 && Year % 100 != 0)//不能被400整除,但是能被4整除并且不能被100整除是闰年
        {
            ret = 1;
        }
        else//不能被400整除,但是不能被4整除或者能被100整除是平年
        {
            ret = 0;
        }
    }

    return ret;
}





/************************************************************************************************
* @ 函 数 名:NTP_DateToTimeStamp
* @ 功能说明:日期转换成时间戳
* @ 参    数:NTP_TimeStruct:时间结构体
* @ 返 回 值:时间戳
************************************************************************************************/
uint32_t NTP_DateToTimeStamp(NTP_TimeTypeDef *p_NTP_TimeStruct)
{
    uint16_t year_temp = NTP_START_TIME_YEAR, month_temp = 1;    //时间戳的起始时间
    uint32_t day_num = 0, second_num = 0;                        //保存当前时间到时间戳起始时间的天数


    //1.计算从NTP_START_TIME_YEAR年到当前时间前一年的总天数   如当前时间为2021.6.15  12.30.30,就计算从NTP_START_TIME_YEAR年到2020年的总天数
    while (year_temp < p_NTP_TimeStruct->year)
    {
        if (NTP_Leapyearjudgment(year_temp))//判断是否为闰年
        {
            day_num += 366;//闰年366天
        }
        else
        {
            day_num += 365;//平年365天
        }
        year_temp++;
    }



    //2.计算当前年份的1月到前一个月的总天数   如当前时间为2021.6.15  12.30.30,就计算从2021年1月到5月的总天数
    while (month_temp < (p_NTP_TimeStruct->month))
    {
        if (NTP_Leapyearjudgment(p_NTP_TimeStruct->year)) //判断当前年是否为闰年
        {
            day_num += leap_month_days[month_temp - 1];//闰年各个月的天数
        }
        else
        {
            day_num += peace_month_days[month_temp - 1];//平年各个月的天数
        }
        month_temp++;
    }



    //3.计算当前月份的1号到前一天的天数  如当前时间为2021.6.15  12.30.30,就计算从2021.6.1到2021.6.14的总天数为14天
    day_num += (p_NTP_TimeStruct->date - 1);



    //4.计算当前时分秒
    second_num = day_num * 24 * 60 * 60; //从1900/1/1 00:00:00到当前时间前一天的总秒数 
    second_num += p_NTP_TimeStruct->hour * 60 * 60;
    second_num += p_NTP_TimeStruct->minute * 60;
    second_num += p_NTP_TimeStruct->second;


    return second_num;
}





/************************************************************************************************
* @ 函 数 名:NTP_TimeStampToDate
* @ 功能说明:时间戳转换成日期
* @ 参    数:Time_Stamp:时间戳      NTP_TimeStruct:时间结构体
* @ 返 回 值:无
************************************************************************************************/
void NTP_TimeStampToDate(uint32_t Time_Stamp, NTP_TimeTypeDef *p_NTP_TimeStruct)
{
    uint32_t totle_day_num = 0, totle_second_num = 0;
    uint16_t remain_day_of_year = 0;
    uint16_t year_temp = 0;
    uint8_t *p_str = NULL;

    totle_day_num = (Time_Stamp) / (24 * 60 * 60);        //计算过去的总天数(注意加括号)
    totle_second_num = (Time_Stamp) % (24 * 60 * 60);    //计算当天过去的秒数

    memset((void *)p_NTP_TimeStruct, 0x00, sizeof(NTP_TimeTypeDef));


    //1.先计算时分秒 HH:MM:SS
    p_NTP_TimeStruct->hour = totle_second_num / 3600;
    p_NTP_TimeStruct->minute = (totle_second_num % 3600) / 60;
    p_NTP_TimeStruct->second = (totle_second_num % 3600) % 60;


    //2.计算哪一年
    p_NTP_TimeStruct->year = NTP_START_TIME_YEAR + (totle_day_num / FOUR_YEAR_DAYS) * 4;    //4年为一个周期,先计算过了几个4年周期,比如当前为2021,计算出来就是2020,那么就是从NTP_START_TIME_YEAR~2019这120年
    remain_day_of_year += totle_day_num % FOUR_YEAR_DAYS;                //4年一个周期剩余的天数
    if (NTP_START_TIME_YEAR == 1900)    //因为1900~1903连续四年都是平年,所以如果是从1900年开始计算,计算完后得重新加1天
    {
        remain_day_of_year++;
    }

    year_temp = NTP_Leapyearjudgment(p_NTP_TimeStruct->year) ? 366 : 365;//计算当前年的天数
    while (remain_day_of_year >= year_temp)  // 判断剩余的天数满不满一年的天数
    {
        p_NTP_TimeStruct->year++;
        remain_day_of_year -= year_temp;
        year_temp = NTP_Leapyearjudgment(p_NTP_TimeStruct->year) ? 366 : 365;
    }



    //3.计算哪一月的哪一天
    p_str = NTP_Leapyearjudgment(p_NTP_TimeStruct->year) ? leap_month_days : peace_month_days;
    remain_day_of_year++;          // 这里开始计算具体日期,remain_day_of_year为 0 时其实是 1 号,所以这里要先 +1
    while (remain_day_of_year > *(p_str + p_NTP_TimeStruct->month))
    {
        remain_day_of_year -= *(p_str + p_NTP_TimeStruct->month);
        p_NTP_TimeStruct->month++;
    }

    p_NTP_TimeStruct->month++;
    p_NTP_TimeStruct->date = remain_day_of_year;

    p_NTP_TimeStruct->week = NTP_WeekCalculate(p_NTP_TimeStruct);
}







/************************************************************************************************
* @ 函 数 名:NTP_GetMessageTime
* @ 功能说明:从NTP回复的报文中获取时间
* @ 参    数:p_Message_Buf:报文缓冲区   Time_Start_Addr:报文中时间的起始位置   p_NTP_TimeStruct:时间结构体
* @ 返 回 值:
************************************************************************************************/
static void NTP_GetMessageTime(uint8_t* p_Message_Buf, uint16_t Time_Start_Addr, NTP_TimeTypeDef *p_NTP_TimeStruct)
{
    unsigned long long second = 0;

    for (uint8_t i = 0; i < 4; i++)
    {
        second = (second << 8) | p_Message_Buf[Time_Start_Addr + i];
    }

    second += 8 * 3600;

    p_NTP_TimeStruct->time_s = second;
}
int main()
{
    WSADATA WSAData;
    SOCKET client_socket;             //客户端的Socket
    SOCKADDR_IN server_addr;           //服务器的地址数据结构
    SOCKADDR_IN sock;

    

    uint8_t  send_buf[BUFFER_SIZE]; //发送数据的缓冲区
    uint8_t  rece_buf[BUFFER_SIZE]; //接受数据的缓冲区


    NTP_TimeTypeDef NTP_TimeStruct;


    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
    {
        printf("初始化失败!");
        return -1;
    }


    //创建客户端的Socket
    client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//创建客户端的Socket
    if (client_socket == INVALID_SOCKET)
    {
        printf("创建套接字失败!");
    }


    /* 设置阻塞超时 */
    struct timeval timeOut;
    timeOut.tv_sec = 5;                 //设置5s超时
    timeOut.tv_usec = 0;
    if (setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeOut, sizeof(timeOut)) < 0)
    {
        printf("time out setting failed\n");
    }



    //配置服务器的IP地址和端口号
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(123);//端口号为4567
    server_addr.sin_addr.s_addr = inet_addr("120.25.108.11");   //127.0.0.1为本电脑IP地址



    int len = sizeof(sock);

    while (1)
    {
        uint8_t message_buf[48] = { 0 };

        memset(&rece_buf, 0, sizeof(rece_buf));

        NTP_GenerateReqMessage(message_buf);

        sendto(client_socket, message_buf, sizeof(message_buf), 0, (SOCKADDR*)&server_addr, sizeof(SOCKADDR));

        int recv_len = recvfrom(client_socket, rece_buf, sizeof(rece_buf), 0, (SOCKADDR*)&sock, &len);


        if (recv_len >= 48)//接收到服务器返回的数据
        {
            for (int i = 0; i < recv_len; i++)
            {
                printf("%02x ", rece_buf[i]);
            }
            printf("\r\n");
            printf("\r\n");


            NTP_GetMessageTime(rece_buf, 40, &NTP_TimeStruct);        //从回复的报文中获取时间,回复数据包中时间的首地址为40
            NTP_TimeStampToDate(NTP_TimeStruct.time_s, &NTP_TimeStruct); //由UTC时间计算日期

            unsigned int time_temp = NTP_DateToTimeStamp(&NTP_TimeStruct);


            printf("%04d-%02d-%02dT%02d:%02d:%02d", NTP_TimeStruct.year, NTP_TimeStruct.month, NTP_TimeStruct.date, NTP_TimeStruct.hour, NTP_TimeStruct.minute, NTP_TimeStruct.second);
            printf("\r\n");
            printf("\r\n");

            printf("%u", time_temp);
            printf("\r\n");
            printf("\r\n");
        }




        Sleep(5000);


    }
    closesocket(client_socket);
    WSACleanup();


    return 0;
}


  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NTP服务器 的相关文章

  • 服务器系统一览表,ntp服务器各种操作系统配置汇总

    服务器配置 首先根据客户端的IP及 网络配置需要对各进行配置 xff0c 修改IP地址及网关地址 其次对于windows服务器可以采用系统自带的NTP服务 xff0c 具体配置如下 xff1a 双击电脑右下角的时间 xff0c 出现如下图所
  • Debian10搭建ntp服务

    文章目录 1 所需设备2 任务描述3 安装ntp服务4 配置ntp服务器4 安装ntpdate客服端5 Debian10Client设置计划任务6 易错总结 1 所需设备 两台Debian10Debian10Server 网卡信息 xff1
  • linux debian ntp,Debian下面的ntp服务(ntpdate)的安装

    NTP Network Time Protocol xff0c 网络时间协议 是用来使网络中的各个计算机时间同步的一种协议 它的用途是把计算机的时钟同步到世界协调时UTC xff0c 其精度在局域网内 Author Samson Date
  • win2003修改ntp服务器,win2003设置ntp服务器配置

    win2003设置ntp服务器配置 内容精选 换一换 以NTP服务器 DNS服务器的操作系统均为SUSE为例 xff1a 登录Linux弹性云服务器 执行以下命令 xff0c 切换至root用户 sudo su sudo su 执行以下命令
  • Ubuntu20.04部署ntp服务

    1 前期准备 系统版本 ip地址 Ubuntu20 04镜像 服务端Ubuntu20 0410 1 0 55ubuntu 20 04 5 live server amd64客户端Ubuntu20 0410 1 0 56ubuntu 20 0
  • debian10 配置ntp服务

    debian10 配置ntp服务 1 安装ntp2 配置3 验证 服务器不能连外网 xff0c 内网中有一台授时服务器 xff0c 内网也搭建了debian10的本地镜像源 1 安装ntp apt install ntp 2 配置 sudo
  • NTP服务器

    1 NTP服务器 NTP协议是网络时间协议 Network Time Protocol xff0c 它是用来同步网络中各个计算机的时间的协议 它的用途是把计算机的时钟同步到世界协调时UTC xff0c 其精度在局域网内可达0 1ms xff
  • NTP协议介绍

    查看原作者 转载自 NTP协议介绍 2013 06 19 14 50 50 转载 SNTP协议原理 SNTP是简单网络时间协议 Simple Network Time protocol 的简称 它是目前Internet网上实现时间同步的一种
  • Linux基础 - NTP时间同步

    博客主页 Passerby Wang的博客 CSDN博客 系统运维 云计算 Linux基础领域博主 所属专栏 Linux基础 上期文章 Linux基础 DNS服务进阶 如觉得博主文章写的不错或对你有所帮助的话 还望大家多多支持呀 关注 点赞
  • 【安装篇】- 基于 VMWARE Oracle Linux7.9 安装 Oracle19c RAC 详细配置方案

    作者 yanwei 来源 墨天轮 https www modb pro db 95684 大家好 我是 JiekeXu 很高兴又和大家见面了 今天和大家一起来看看 Linux7 9 安装 Oracle19c RAC 详细配置方案 欢迎点击上
  • 发送到 NTP 服务器的 '\x1b' + 47 * '\0' 消息是什么意思?

    我正在开发 NTP 客户端 其他一些线程表明包含 x1b 47 0 的消息被发送到 NTP 服务器 但这些线程都没有解释该消息的实际含义或发送原因 我尝试查看 NTP RFC 但也无法在其中找到任何有关它的信息 x1b 47 0 表示48字
  • 将 64 位时间戳转换为可读值

    在我的数据集中 我有两个时间戳列 第一个是自应用程序启动以来的微秒 例如 1400805323 第二个被描述为 64 位时间戳 我希望它能够指示时钟时间 使用 1901 年 1 月 1 日开始的秒数 NTP 格式 64 位 时间戳示例 12
  • 将 Linux 系统时钟同步到 Windows NTP 服务

    我有一台 Linux PC 作为时钟客户端 我想使用 ntpdate 将此 PC 的时间与同一网络上同一空间中的 Windows PC 同步 我无法找到如何做到这一点 尽管我认为 Windows 时间服务是一个 NTP 服务器 但这并不像调
  • 与计算机同步互联网时间

    所以我制作了一个具有许可证检查功能的程序 该程序仅适用于有限数量的受信任的人 所以我知道他们不会尝试篡改它 我想要做的是将计算机时钟与互联网时间 例如 time windows com 或任何受信任的时间 同步 如果计算机时钟与互联网不匹配
  • iPhone 的网络时间协议

    我正在编写一个需要精确计时的应用程序 问完后这个问题 https stackoverflow com questions 2264197 how to accurately sync time between iphones 我决定使用 N
  • 在 Android 应用程序中从 Web 获取 UTC 日期

    我想要一个UTC date对于我的 Android 应用程序来说 它是独立于设备 和用户 的 我听说过一些事情 比如从 NTP 服务器获取日期 但无法从 google 或 SO 找到任何帮助 那么任何人都可以帮我提供一些代码片段或链接吗 提
  • NTP请求包

    我试图弄清楚我需要在 NTP 请求包中发送 客户端 什么才能从服务器检索 NTP 包 我正在 Cortex M3 Stellaris LM3S6965 上使用 LWIP 据我了解 我将收到 UDP 标头 然后收到具有不同时间戳的 NTP 协
  • 为什么ntpd服务重启后没有自动启动? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我安装后ntpd via yum我运行命令systemctl enable ntpd service并重新启动计算机 得到 shell 提
  • 同步通过 LAN 电缆连接的两台 Windows 7 计算机之间的时间

    我有许多笔记本电脑 它们运行我们的应用程序 同时通过以太网电缆成对连接 但未连接到任何外部网络或互联网 时间 我需要连接对来同步其系统时间 但由于每台计算机都需要能够与任何其他计算机同步 因此我无法将一台计算机定义为时间服务器 而另一台计算
  • 尽管使用了 NTP 偏移量,设备仍会在几秒后启动指令

    背景 我有两台物理设备 一台 Galaxy S3 手机 和一台 Asus 700T 平板电脑 我想在同一时间执行同一组指令 因此 我使用的是 Android 的平台框架 基本 SNTP 客户端代码 https github com andr

随机推荐

  • 51单片机LCD1602液晶屏显示字符,字符串,(有)无符号整数,十六进制数,二进制数等

    1 前言 LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块 液晶显示模块具有体积小 功耗低 显示内容丰富 超薄轻巧等优点 xff0c 在嵌入式应用系统中得到越来越广泛的应用 xff0c 这讲中向大家介绍的LCD1602 液晶显示模
  • 51单片机——DS1302时钟

    目录 1 前言 1 1 实验现象 2 DS1302的介绍 2 1 DS1302的引脚定义以及应用电路 2 2 DS1302内部结构 2 21 DS1302内部特殊寄存器 2 22 时序 2 3 BCD码 3 源码 3 1 main c 3
  • 编译安装GCC12.2.0

    编译安装GCC 记录一下 xff0c 免得每次到处找 安装GCC12 2 0 xff0c 其他版本一样 源码下载地址 xff1a https ftp gnu org gnu gcc 备注 xff1a 配置若有不明白的 xff0c 多用 co
  • 安装vim

    sudo apt get install vim 确认后按y就行了 vim的三种模式 1 普通模式 当vim打开的时候就直接进入普通模式 在普通模式下可以进入命令 插入模式 2 插入模式 可以通过普通模式进入插入模式 插入模式可以编辑文本
  • jetson tx2 刷机,安装 cuda、opencv 详细教程

    jetson tx2 刷机 xff0c 安装 cuda opencv 详细教程 jetson tx2 的详细介绍和用途可见官网 xff1a Nvidia jetson tx2 接下来主要说明jetson tx2 详细刷机过程以及在过程中踩过
  • PX4 编译报错问题解决方法、PX4切换固定版本编译

    PX4 Autopilot 编译报错问题解决方法 1 make 2 没有规则可制作目标 dirlinks 停止 1 1159 Generating platforms nuttx NuttX nuttx config FAILED plat
  • ubuntu 系统狠慢 或者很卡的原因

    1 涉及内存小或者虚拟SWAP分区调整问题 可以通过 系统监视器 进行查看 在UBUNTU系统里面 xff0c 并不是你的物理内存全部耗尽之后 xff0c 系统才使用swap分区 xff01 系统的swappiness设定值 xff0c 对
  • 技巧1——怎样查看linux发行版本名称和版本号?

    假如我们加入了一家新公司 xff0c 需要为开发团队安装所需要的软件并且重启服务 首先要弄清楚它们运行在什么发行版本上以及在哪个版本的系统上 xff0c 才能正确的完成后续的工作 作为一名系统管理员 xff0c 充分了解系统信息是首要的任务
  • 种群共生模型

    种群共生模型 种群共生模型 1 1 背景 1 2 参数假设 1 3 分析 1 4 模型构建 1 5 模型求解 1 6 讨论平衡点稳定性 种群共生模型 1 1 背景 在自然界中 种族的共生现象是比较普遍的 如鳄鱼与千鸟 千鸟不但在鳄鱼身上寻找
  • opendaylight学习笔记——Flows

    Flow java中 private static final String WEB NAME 61 34 Flows 34 定义了在网页中显示时的名称 private static final String WEB ID 61 34 fl
  • NB-IoT 物理层相关

    写在前面 本文作为简单说明 xff0c 详细需具体查阅文档 1 关于 PRB 的理解 RB xff08 Resource Block xff09 xff0c 用于描述某些物理信道到资源元素的映射 xff0c 它有两个概念 xff1a VRB
  • 以太网详解(一)-MAC/PHY/MII/RMII/GMII/RGMII基本介绍

    网络设备中肯定离开不MAC和PHY xff0c 本篇文章将详细介绍下以太网中一些常见术语与接口 MAC和PHY结构 从硬件角度来看以太网是由CPU xff0c MAC xff0c PHY三部分组成的 xff0c 如下图示意 xff1a 上图
  • ubuntu(linux)下smb完整搭建流程-----原来如此简单,一步到位!!!!!!

    1 查看ubuntu版本号命令 lsb release a 2 下载安装 sudo apt get insall samba FAQ 如果出现apt install时候遇到E Unable to fetch some archives ma
  • xilinx fpga xdma

    一 下载XDMA文件 输入命令 sudo git clone https github com Xilinx dma ip drivers 二 编译文件 进入xdma文件夹 xff1a cd dma ip drivers XDMA linu
  • 网络通信原理及流程

    网络通信原理 1 1 互联网的本质就是一系列的网络协议 一台硬设有了操作系统 xff0c 然后装上软件你就可以正常使用了 xff0c 然而你也只能自己使用像这样 xff0c 每个人都拥有一台自己的机器 xff0c 然而彼此孤立吗 xff0c
  • LTE核心网介绍

    1 LTE网络架构 EPS包括核心网EPC xff08 EPC又包括MME xff08 信令处理部分 xff09 S GW xff08 数据处理部分 xff09 P GW xff09 E UTRAN xff08 只包含基站eNodeB一个网
  • FreeRTOS启动第一个任务和任务的切换(Cortex-M4)

    调度器是FreeRTOS操作系统的核心 xff0c 主要负责任务切换 xff0c 即在就绪任务中找出最高优先级的任务 xff0c 并使之获得CPU运行权 调度器并非自动运行的 xff0c 需要人为启动它 API函数vTaskStartSch
  • 1G~5G 网络结构演进过程

    无线接入网 xff1a 负责接收用户终端的无线信号 xff0c 由此接入到通信网络 xff1b 核心网 xff1a 对用户数据的管理及具体业务处理 xff0c 并作为承载网络提供到外部网络的接口 1 GSM网络结构 xff08 2G xff
  • 1G-5G 基站架构演进

    1 2G 2G通信系统采用3级网络架构 xff0c 即 xff1a BTS BSC 核心网 2G核心网同时包含CS域和PS域 2G通信系统起初主要采用一体式基站架构 一体式基站架构如下图所示 xff0c 基站的天线位于铁塔上 xff0c 其
  • NTP服务器

    1 NTP服务器 NTP协议是网络时间协议 Network Time Protocol xff0c 它是用来同步网络中各个计算机的时间的协议 它的用途是把计算机的时钟同步到世界协调时UTC xff0c 其精度在局域网内可达0 1ms xff