精华内容
下载资源
问答
  • NTP协议

    2019-02-23 15:47:24
    NTP协议简介   关于下面的C++代码,我是基于博客园席纳霍霍的代码进行修改的。他的代码在我的系统里运行时间不对。非常感谢上面3位作者无私奉献。 C++ 代码: #include <stdio.h&g...

    网络时间协议,英文名称:Network Time Protocol(NTP

     

     

    linux C/C++实现同步NTP时间

     

    简单的NTP客户端-C语言实现

     

    NTP协议简介

     

    关于下面的C++代码,我是基于博客园席纳霍霍的代码进行修改的。他的代码在我的系统里运行时间不对。非常感谢上面3位作者无私奉献。

    C++ 代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include<iostream>
    #include <unistd.h>
    #include <sys/select.h>
     #include<sys/time.h> 
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <errno.h>
    #include <endian.h>
    
    #define VERSION_3           3
    #define VERSION_4           4
    
    #define MODE_CLIENT         3
    #define MODE_SERVER         4
     
    #define NTP_LI              0
    #define NTP_VN              VERSION_3   
    #define NTP_MODE            MODE_CLIENT
    #define NTP_STRATUM         0
    #define NTP_POLL            4
    #define NTP_PRECISION       -6
    
    #define NTP_HLEN            48
    
    #define NTP_PORT            123
    #define NTP_SERVER          "182.92.12.11"
    
    #define TIMEOUT             10
    
    #define BUFSIZE             1500
    
    #define JAN_1970            0x83aa7e80
    
    #define NTP_CONV_FRAC32(x)  (uint64_t) ((x) * ((uint64_t)1<<32))    
    #define NTP_REVE_FRAC32(x)  ((double) ((double) (x) / ((uint64_t)1<<32)))   
    
    #define NTP_CONV_FRAC16(x)  (uint32_t) ((x) * ((uint32_t)1<<16))    
    #define NTP_REVE_FRAC16(x)  ((double)((double) (x) / ((uint32_t)1<<16)))    
    
    
    #define USEC2FRAC(x)        ((uint32_t) NTP_CONV_FRAC32( (x) / 1000000.0 )) 
    #define FRAC2USEC(x)        ((uint32_t) NTP_REVE_FRAC32( (x) * 1000000.0 )) 
    
    
    #define NTP_LFIXED2DOUBLE(x)    ((double) ( ntohl(((struct l_fixedpt *) (x))->intpart) - JAN_1970 + FRAC2USEC(ntohl(((struct l_fixedpt *) (x))->fracpart)) / 1000000.0 ))   
    
    using namespace std;
    struct s_fixedpt {
        uint16_t    intpart;
        uint16_t    fracpart;
    };
    
    struct l_fixedpt {
        uint32_t    intpart;
        uint32_t    fracpart;
    };
    
    
    struct ntphdr {
    #if __BYTE_ORDER == __BID_ENDIAN
        unsigned int    ntp_li:2;
        unsigned int    ntp_vn:3;
        unsigned int    ntp_mode:3;
    #endif
    #if __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned int    ntp_mode:3;
        unsigned int    ntp_vn:3;
        unsigned int    ntp_li:2;
    #endif
        uint8_t         ntp_stratum;
        uint8_t         ntp_poll;
        int8_t          ntp_precision;
        struct s_fixedpt    ntp_rtdelay;
        struct s_fixedpt    ntp_rtdispersion;
        uint32_t            ntp_refid;
        struct l_fixedpt    ntp_refts;
        struct l_fixedpt    ntp_orits;
        struct l_fixedpt    ntp_recvts;
        struct l_fixedpt    ntp_transts;
    };
    
    
    in_addr_t inet_host(const char *host)
    {
        in_addr_t saddr;
        struct hostent *hostent;
    
        if ((saddr = inet_addr(host)) == INADDR_NONE) {
            if ((hostent = gethostbyname(host)) == NULL)
                return INADDR_NONE;
    
            memmove(&saddr, hostent->h_addr, hostent->h_length);
        }
    
        return saddr;
    }
    
    
    int get_ntp_packet(void *buf, size_t *size)  //构建并发送NTP请求报文
    {
        struct ntphdr *ntp;
        struct timeval tv;
    
    
        if (!size || *size<NTP_HLEN)
            return -1;
    
        memset(buf, 0, *size);
    
        ntp = (struct ntphdr *) buf;
        ntp->ntp_li = NTP_LI;
        ntp->ntp_vn = NTP_VN;
        ntp->ntp_mode = NTP_MODE;
        ntp->ntp_stratum = NTP_STRATUM;
        ntp->ntp_poll = NTP_POLL;
        ntp->ntp_precision = NTP_PRECISION;
    
        gettimeofday(&tv, NULL);  //把目前的时间用tv 结构体返回
        ntp->ntp_transts.intpart = htonl(tv.tv_sec + JAN_1970);
        ntp->ntp_transts.fracpart = htonl(USEC2FRAC(tv.tv_usec));
    
        *size = NTP_HLEN;
    
        return 0;
    }
    
    
    
    double get_rrt(const struct ntphdr *ntp, const struct timeval *recvtv)  //往返时延
    {
        double t1, t2, t3, t4;
    
        t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits);
        t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts);
        t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts);
        t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0;
    
        return (t4 - t1) - (t3 - t2);
    }
    
    
    double get_offset(const struct ntphdr *ntp, const struct timeval *recvtv)  //偏移量
    {
        double t1, t2, t3, t4;
    
        t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits);
        t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts);
        t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts);
        t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0;
    
        return ((t2 - t1) + (t3 - t4)) / 2;
    }
    
    
    
    
    int main(int argc, char *argv[])
    {    
        char dateBuf[64] = {0};
        char cmd[128] = {0};
        tm* local; 
        char buf[BUFSIZE];
        size_t nbytes;
        int sockfd, maxfd1;
        struct sockaddr_in servaddr;
        fd_set readfds;
        struct timeval timeout, recvtv, tv;
        double offset;
    
        // if (argc != 2) {
            // usage();
            // exit(-1);
       
    
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(NTP_PORT);
        servaddr.sin_addr.s_addr = inet_host("119.28.183.184");
        
        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            perror("socket error");
            exit(-1);
        }
    
        if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) != 0) {  
            perror("connect error");
            exit(-1);
        }
        nbytes = BUFSIZE;
        if (get_ntp_packet(buf, &nbytes) != 0) {
            fprintf(stderr, "construct ntp request error \n");
            exit(-1);
        }
        send(sockfd, buf, nbytes, 0);
    
    
        FD_ZERO(&readfds);
        FD_SET(sockfd, &readfds);
        maxfd1 = sockfd + 1;
    
    
        timeout.tv_sec = TIMEOUT;
        timeout.tv_usec = 0;
        
        if (select(maxfd1, &readfds, NULL, NULL, &timeout) > 0) {
            if (FD_ISSET(sockfd, &readfds)) 
            {
                if ((nbytes = recv(sockfd, buf, BUFSIZE, 0)) < 0)  
                {
                    perror("recv error");
                    exit(-1);
                }
                
                //计算C/S时间偏移量
                gettimeofday(&recvtv, NULL);
                offset = get_offset((struct ntphdr *) buf, &recvtv);    
                更新系统时间
    
                gettimeofday(&tv, NULL);
                
                tv.tv_sec += (int) offset ;//+28800;//alen
                tv.tv_usec += offset - (int) offset;
                
                local = localtime((time_t *) &tv.tv_sec); 
                strftime(dateBuf, 64, "%Y-%m-%d %H:%M:%S", local);
                sprintf(cmd, "system busybox date -s \"%s\"", dateBuf);
    
    	    cout << cmd <<endl;
    	    //printf("%s\n",cmd); //alen
                
                printf("%s \n", ctime((time_t *) &tv.tv_sec));
                
    
            }
        }
    
        close(sockfd);
    
        return 0;
    }
    

     

    C代码:

    /* ntpclient.c */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    #include <unistd.h>
    #include <sys/select.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <errno.h>
    #include <endian.h>
    
    #define VERSION_3           3
    #define VERSION_4           4
    
    #define MODE_CLIENT         3
    #define MODE_SERVER         4
    
    
    #define NTP_LI              0
    #define NTP_VN              VERSION_3   
    #define NTP_MODE            MODE_CLIENT
    #define NTP_STRATUM         0
    #define NTP_POLL            4
    #define NTP_PRECISION       -6
    
    #define NTP_HLEN            48
    
    #define NTP_PORT            123
    #define NTP_SERVER          "182.92.12.11"
    
    #define TIMEOUT             10
    
    #define BUFSIZE             1500
    
    #define JAN_1970            0x83aa7e80
    
    #define NTP_CONV_FRAC32(x)  (uint64_t) ((x) * ((uint64_t)1<<32))    
    #define NTP_REVE_FRAC32(x)  ((double) ((double) (x) / ((uint64_t)1<<32)))   
    
    #define NTP_CONV_FRAC16(x)  (uint32_t) ((x) * ((uint32_t)1<<16))    
    #define NTP_REVE_FRAC16(x)  ((double)((double) (x) / ((uint32_t)1<<16)))    
    
    
    #define USEC2FRAC(x)        ((uint32_t) NTP_CONV_FRAC32( (x) / 1000000.0 )) 
    #define FRAC2USEC(x)        ((uint32_t) NTP_REVE_FRAC32( (x) * 1000000.0 )) 
    
    
    #define NTP_LFIXED2DOUBLE(x)    ((double) ( ntohl(((struct l_fixedpt *) (x))->intpart) - JAN_1970 + FRAC2USEC(ntohl(((struct l_fixedpt *) (x))->fracpart)) / 1000000.0 ))   
    
    
    struct s_fixedpt {
        uint16_t    intpart;
        uint16_t    fracpart;
    };
    
    struct l_fixedpt {
        uint32_t    intpart;
        uint32_t    fracpart;
    };
    
    
    struct ntphdr {
    #if __BYTE_ORDER == __BID_ENDIAN
        unsigned int    ntp_li:2;
        unsigned int    ntp_vn:3;
        unsigned int    ntp_mode:3;
    #endif
    #if __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned int    ntp_mode:3;
        unsigned int    ntp_vn:3;
        unsigned int    ntp_li:2;
    #endif
        uint8_t         ntp_stratum;
        uint8_t         ntp_poll;
        int8_t          ntp_precision;
        struct s_fixedpt    ntp_rtdelay;
        struct s_fixedpt    ntp_rtdispersion;
        uint32_t            ntp_refid;
        struct l_fixedpt    ntp_refts;
        struct l_fixedpt    ntp_orits;
        struct l_fixedpt    ntp_recvts;
        struct l_fixedpt    ntp_transts;
    };
    
    
    in_addr_t inet_host(const char *host)
    {
        in_addr_t saddr;
        struct hostent *hostent;
    
        if ((saddr = inet_addr(host)) == INADDR_NONE) {
            if ((hostent = gethostbyname(host)) == NULL)
                return INADDR_NONE;
    
            memmove(&saddr, hostent->h_addr, hostent->h_length);
        }
    
        return saddr;
    }
    
    
    int get_ntp_packet(void *buf, size_t *size)
    {
        struct ntphdr *ntp;
        struct timeval tv;
    
    
        if (!size || *size<NTP_HLEN)
            return -1;
    
        memset(buf, 0, *size);
    
        ntp = (struct ntphdr *) buf;
        ntp->ntp_li = NTP_LI;
        ntp->ntp_vn = NTP_VN;
        ntp->ntp_mode = NTP_MODE;
        ntp->ntp_stratum = NTP_STRATUM;
        ntp->ntp_poll = NTP_POLL;
        ntp->ntp_precision = NTP_PRECISION;
    
        gettimeofday(&tv, NULL);
        ntp->ntp_transts.intpart = htonl(tv.tv_sec + JAN_1970);
        ntp->ntp_transts.fracpart = htonl(USEC2FRAC(tv.tv_usec));
    
        *size = NTP_HLEN;
    
        return 0;
    }
    
    
    void print_ntp(struct ntphdr *ntp)
    {
        time_t time;
    
        printf("LI:\t%d \n", ntp->ntp_li);
        printf("VN:\t%d \n", ntp->ntp_vn);
        printf("Mode:\t%d \n", ntp->ntp_mode);
        printf("Stratum:\t%d \n", ntp->ntp_stratum);
        printf("Poll:\t%d \n", ntp->ntp_poll);
        printf("precision:\t%d \n", ntp->ntp_precision);
    
        printf("Route delay:\t %lf \n",
            ntohs(ntp->ntp_rtdelay.intpart) + NTP_REVE_FRAC16(ntohs(ntp->ntp_rtdelay.fracpart)));
        printf("Route Dispersion:\t%lf \n",
            ntohs(ntp->ntp_rtdispersion.intpart) + NTP_REVE_FRAC16(ntohs(ntp->ntp_rtdispersion.fracpart)));
        printf("Referencd ID:\t %d \n", ntohl(ntp->ntp_refid));
    
    
        time = ntohl(ntp->ntp_refts.intpart) - JAN_1970;
        printf("Reference:\t%d %ld %s \n",
            ntohl(ntp->ntp_refts.intpart) - JAN_1970,
            FRAC2USEC(ntohl(ntp->ntp_refts.fracpart)),
            ctime(&time));
    
        time = ntohl(ntp->ntp_orits.intpart) - JAN_1970;
        printf("Originate:\t%d %d frac=%ld (%s) \n",
            ntohl(ntp->ntp_orits.intpart) - JAN_1970,
            FRAC2USEC(ntohl(ntp->ntp_orits.fracpart)),
            ntohl(ntp->ntp_orits.fracpart),
            ctime(&time) );
    
        time = ntohl(ntp->ntp_recvts.intpart) - JAN_1970;
        printf("Receive:\t%d %d (%s) \n",
            ntohl(ntp->ntp_recvts.intpart) - JAN_1970,
            FRAC2USEC(ntohl(ntp->ntp_recvts.fracpart)),
            ctime(&time) );
    
        time = ntohl(ntp->ntp_transts.intpart) - JAN_1970;
        printf("Transmit:\t%d %d (%s) \n",
            ntohl(ntp->ntp_transts.intpart) - JAN_1970,
            FRAC2USEC(ntohl(ntp->ntp_transts.fracpart)),
            ctime(&time) );
    }
    
    
    double get_rrt(const struct ntphdr *ntp, const struct timeval *recvtv)
    {
        double t1, t2, t3, t4;
    
        t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits);
        t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts);
        t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts);
        t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0;
    
        return (t4 - t1) - (t3 - t2);
    }
    
    
    double get_offset(const struct ntphdr *ntp, const struct timeval *recvtv)
    {
        double t1, t2, t3, t4;
    
        t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits);
        t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts);
        t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts);
        t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0;
    
        return ((t2 - t1) + (t3 - t4)) / 2;
    }
    
    
    void usage(void)
    {
        fprintf(stderr,
            "Usage : ntpclient"
            " destination"
            "\n"
        );
    }
    
    
    int main(int argc, char *argv[])
    {
        char buf[BUFSIZE];
        size_t nbytes;
        int sockfd, maxfd1;
        struct sockaddr_in servaddr;
        fd_set readfds;
        struct timeval timeout, recvtv, tv;
        double offset;
    
        if (argc != 2) {
            usage();
            exit(-1);
        }
    
    
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(NTP_PORT);
        servaddr.sin_addr.s_addr = inet_host(argv[1]);
    
        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            perror("socket error");
            exit(-1);
        }
    
        if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) != 0) {
            perror("connect error");
            exit(-1);
        }
    
        nbytes = BUFSIZE;
        if (get_ntp_packet(buf, &nbytes) != 0) {
            fprintf(stderr, "construct ntp request error \n");
            exit(-1);
        }
        send(sockfd, buf, nbytes, 0);
    
    
        FD_ZERO(&readfds);
        FD_SET(sockfd, &readfds);
        maxfd1 = sockfd + 1;
    
        timeout.tv_sec = TIMEOUT;
        timeout.tv_usec = 0;
    
        if (select(maxfd1, &readfds, NULL, NULL, &timeout) > 0) {
            if (FD_ISSET(sockfd, &readfds)) {
                if ((nbytes = recv(sockfd, buf, BUFSIZE, 0)) < 0) {
                    perror("recv error");
                    exit(-1);
                }
    
                gettimeofday(&recvtv, NULL);
                offset = get_offset((struct ntphdr *) buf, &recvtv);
    
                gettimeofday(&tv, NULL);
                tv.tv_sec += (int) offset;
                tv.tv_usec += offset - (int) offset;
    
                if (settimeofday(&tv, NULL) != 0) {
                    perror("settimeofday error");
                    exit(-1);
                }
                printf("%s \n", ctime((time_t *) &tv.tv_sec));
            }
        }
    
        close(sockfd);
    
        return 0;
    }

     

    展开全文
  • NTP 协议

    千次阅读 2011-05-13 14:56:00
    NTP协议属于应用层协议,是用于在分布式时间服务器和客户端之间进行时间同步的,它定义了协议实现过程中所使用的结构、算法、实体和协议。NTP协议是 基于IP和UDP的,也可以被其它协议组使用。NTP是从时间协议

    NTP: Network Time Protocal

    一、定义:
    为实现高精确度的时间同步,而设计的网络时钟同步协议。在Linux系统中,它的最新实现是NTP 4.0(一个分布式的网络时钟同步程序)。相关定义和实现参看RFC1305和www.ntp.org 。 NTP协议属于应用层协议,是用于在分布式时间服务器和客户端之间进行时间同步的,它定义了协议实现过程中所使用的结构、算法、实体和协议。NTP协议是 基于IP和UDP的,也可以被其它协议组使用。NTP是从时间协议(TIME PROTOCOL)和ICMP 时间戳报文(ICMP TIMESTAMP MESSAGE)演变而来,主要是从准确性和强壮性方面进行了特殊的设计。
     NTP的优点:
    采用分层的方法来定义时钟的准确性,可以迅速同步网络中各   台设备的时间。
    支持访问控制和MD5验证。
    可以选择采用单播、广播或组播发送协议报文。

     
     图1 NTP 工作原理

    上图1所示的是NTP基本工作原理,路由器A和路由器B通过网络相连,它们都有自己独立的系统时钟,要实现各自系统时钟的自动同步,作如下假设:
    路由器A和B的系统时钟同步之前,路由器A的时钟设定为10:00:00am,路由器B的时钟设定为11:00:00am。
    以路由器B为NTP时间服务器,即路由器A将使自己的时钟与路由器B的时钟同步。
    数据包在路由器A和B之间单向传输所需要的时间为1秒。

    系统时钟同步的工作过程如下:
    路由器A发送一个NTP消息包给路由器B,该消息包带有它离开路由器A时的时间戳,该时间戳为10:00:00am(T1)。
    当此NTP消息包到达路由器B时,路由器B加上自己的时间戳,该时间戳为11:00:01am(T2)。
    当此NTP消息包离开路由器B时,路由器B再加上自己的时间戳,该时间戳为11:00:02am(T3)。
    当路由器A接收到该响应消息包时,加上一个新的时间戳,该时间戳为10:00:03am(T4)。

    至此,RouterA 拥有足够信息来计算以下两个重要参数:
    NTP 消息来回一个周期的时延:Delay=(T4-T1)-(T3-T2)。
    RouterA 相对RouterB 的时间差:Offset=((T2-T1)+(T3-T4))/2。
    RouterA 根据这些信息来设定自己的时钟,实现与RouterB 的时钟同步。


    NTP的四种工作模式:
    服务器 / 客户模式(server / client)              
    这种模式只需要在客户端配置,服务器端除了配置NTP 主时钟外,不需要进行其他专门配置。并且,只能是客户端同步到服务器,服务器不会同步到客户端。
    配置完成后:
    客户端向服务器发送同步请求报文,报文中的 Mode 字段设置为3(客户模式)。
    服务器端收到请求报文后,自动工作在服务器模式,并发送应答报文,报文中的
    Mode 字段设置为4(服务器模式)。
    客户端收到应答报文后,进行时钟过滤和选择,并同步到优选的服务器端。

    对等体模式(symmetric active / symmetric passive)
    在对等体模式中,只需要在主动对等体(Symmetric active)端进行配置,被动对等体
    (Symmetric passive)端无需配置NTP 命令。对等体模式下,主动对等体和被动对等体可以互相同步,等级低(层数大)的对等体向等级高(层数小)的对等体同步。
    配置完成后:
    主动对等体向被动对等体发送同步请求报文,报文中的 Mode 字段设置为1(主动对等体)。
    被动对等体收到请求报文后,自动工作在被动对等体模式,并发送应答报文,报文中的Mode 字段设置为2(被动对等体)。

    广播模式(broadcast server / broadcast client)
    在广播模式下,服务器端和客户端都需要配置相关命令。配置完成后:
    服务器端周期性向广播地址 255.255.255.255 发送时钟同步报文。
    客户端侦听来自服务器的广播消息包。
    客户端接收到第一个广播消息包后,为估计网络延迟,客户端先启用一个短暂的服务器/客户端模式与远程服务器交换消息。
    然后,客户端进入广播客户端模式,继续侦听广播消息包的到来,根据到来的广播消息包对本地时钟进行同步。

    组播模式(multicast server / multicast client)
    在组播模式下,服务器端和客户端都需要配置相关命令。配置完成后:
    服务器端周期性向组播目的地址 224.0.1.1 发送时钟同步报文。
    客户端侦听来自服务器的组播消息包。
    当客户端接收到第一个组播消息包后,为估计网络延迟,客户端先启用一个短暂的服务器/客户端模式与远程服务器交换消息。
     然后,客户端进入组播客户端模式,继续侦听组播消息包的到来,根据到来的组播消息包对本地时钟进行同步。

    NTP的工作模式MODE。不同值表示的含义如下:
     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,内部使用预留
    我们采用第一和第二种模式。

    NTP网络结构
     
     图2 NTP树形网络结构(同层之间还可以互联同步,这样更稳定)
    NTP 模型中,多个通过有线或无线系统与国家标准时钟同步的主   参考源被连接到网络内被广泛访问的资源,如:骨干网关,这些主参考源作为主时间服务器运行在网络中。NTP的目的就是通过INTERNET将这些主时间服 务器的计时信息传送到其它时间服务器,并且反复核对时钟以减少由于仪器或传播失误而产生的误差。另外一些局网内部的运行NTP的主机或网关,作为二级时间 服务器运行在网络中。二级时间服务器通过NTP将时间信息传送到局网内部的其它主机。为了提高可靠性,可以在被选择的主机上配备准确性较低但比较便宜的 RADIO CLOCK作为备份,以备主参考服务器和/或次级时间服务器出错或者是主机与时间服务器之间的通信发生故障时使用。

    二 、NTP实现介绍(Linux下)
    ntpd :NTP Demaon程序:
    ntpd是开机自启动的服务,会自动和远端的同步服务器进行时间的同步,注意:和ntpdate不同的是,它是慢同步,而ntpdate是立即同步。使用ntpd同步的好处对于那些对时间稳定性要求高的服务,可以提供缓慢稳定的时间
    变化,而不是一步改变。


    ntp.conf配置文件说明:ntp.conf文件里面配置的是一些访问安全策略和ntp命令。具体如下:
    主要的命令和选项说明

    1 Access Control Options
    1.1 discard设置速率控制,保护NTP服务器受客户端过多的干扰。
    discard [average vag] [minimum min] [monitor prob]
    vag: 规定最小的平均包间隙时间,以log2的形式,单位为妙,默认值是3
    min: 规定最小的包间隙时间,形式如上
    prob:规定最近收到包超过最大接受单元MRU的概率。用于优化性能。

    1.2 restrict设置访问控制的策略
    restrict default [flag][...]  必须是第一个,对所有的(address 0.0.0.0, mask 0.0.0.0 for IPv4 and address :: mask :: for IPv6)默认的规定
    restrict source [flag][...]  对source的规定
    restrict address [mask mask] [flag][...] 对网络address的规定
    address:xxx.xxx.xxx.xxx形式的主机或网络地址,也可以是dns名字。
    mask :掩码,全1 指明address是一个主机地址
    常见的flag:
    flake: 以0.1的概率丢弃NTP包,测试用。
    ignore :拒绝所有的包,包括ntpq和ntpdc的查询包。
    kod : 如果设置了limited标识和使用discard命令控制速率,则返回一个Kod(kiss-O'-death)包。
    limited : 拒绝服务,如果数据包超过了diacard设置的速率。对ntpq和ntpdc不起作用。
    lowpriotrap:对匹配的主机的trap设置低优先级。
    mssntp :启动Microsoft的简单ntp协议
    nomodify:拒绝ntpq和ntpdc的修改消息。时间同步服务不受影响
    noquery : 拒绝ntpq和ntpdc的查询,时间同步服务不受影响
    nopeer :拒绝没有认证的消息包,主要针对association相关的包。
    noserve :拒绝除ntpq和ntpdc的消息报文。
    notrap :拒绝对匹配主机提供Mode 6的控制消息服务。
    notrust :拒绝对不经过加密验证的包服务
    ntpport :拒绝对源端口是NTP指定端口123的数据包服务
    version :拒绝对非当前版本的数据包服务

    1.3 例子
    An example may clarify how it works. Our campus has two class-B networks, 128.4 for the ECE and CIS departments and 128.175 for the rest of campus. Let's assume (not true!) that subnet 128.4.1 homes critical services like class rosters and spread sheets. A suitable ACL might be

    restrict default nopeer     # deny new associations
    restrict 128.175.0.0 mask 255.255.0.0   # allow campus access
    restrict 128.4.0.0 mask 255.255.0.0 none # allow ECE and CIS access
    restrict 128.4.1.0 mask 255.255.255.0 notrust # require authentication on subnet 1
    restrict time.nist.gov 

    2 Reference Clock Commands 参考时钟(主时钟)命令
    2.1 配置参考时钟
    server 127.127.t.u [prefer] [mode int] [minpoll int] [maxpoll int]
    prefer :将参考时钟设为首选
    mode :规定模式的值
    minpoll 和maxpoll :规定查询的间隔,以2的幕的形式。取值范围在4-17。minpoll和maxpoll默认值都是6,即2的6次方=64秒。对应 Modem的参考时钟,minpoll去10,即17.1分钟,maxpoll默认值是14,即4.5小时。 

    2.2 配置参考时钟的其他信息,必须紧跟着server后面
    fudge 127.127.t.u [time1 sec] [time2 sec] [stratum int] [refid string] [flag1 0|1] [flag2 0|1] [flag3 0|1] [flag4 0|1]
    time1  : 常数,用来调成偏移offset值
    time2 : 设置一个固点的小数,这个与驱动无关。
    stratum : 设置一个0-15的一个层数。值越小,表明离时间源更近,更准确。
    refid : 设置ASCII形式的字符串ID。

    3 Server Command
    3.1 配置命令: 规定时间服务器的地址即操作模式。
    server address [options ...]
    peer address [options ...]
    broadcast address [options ...]
    manycastclient address [options ...]
    pool address [options ...]
    unpeer [address | associd]
    server : 以c/s模式,与远程的服务器或本地参考时钟持续的调整时间
    peer : 以symmetric-active模式,与远端的节点同步时间。即同层的节点间同步,可以增加稳定性。
    broadcast:对广播和多播地址,调整
    manycastclient: 根据多播组的地址进行调整。
    pool : 调整与以DNS名字规定的池的关联。
    unpeer : 根据地址或ID,移除以前注册的关联,可以用ntpq在运行时配置。
    注:server 与 peer的区别:server是上一级的时间服务器。peer是同级的同步节点。

    options说明:
    autokey :发送和接受经过Autokey机制验证的数据包
    burst :当server可达时,以默认发包速率的8倍向服务器发包。
    iburst : 当server不可达时,以默认发包速率的8倍向服务器发包。
    key :发送和接受经过symmetric key机制验证的数据包.
    prefer : 设置首选
    ttl :为多播和广播数据包设置ttl
    version :设置version number。1-4,默认值是4
    preempt :设置关联为可抢占式的。
    noselect :标识server 或peer 不执行selection算法,即不会被选择作为源来同步时间

    其他命令
    broadcastclient   :enable broadcast client
    manycastserver address [...] : enable manycast server
    multicastclient address [...]  : enable multicast client

    4 Miscellaneous Commands
    broadcastdelay - specify broadcast delay
    driftfile - specify frequency file
    enable - enable options
    disable - disable options
    includefile - specify include file
    interface - specify which local network addresses to use
    leapfile - specify leapseconds file
    logconfig - configure log file
    nic - alias for interface
    mru - control monitor MRU list limits
    phone - specify modem phone numbers
    saveconfigdir - specify saveconfig directory
    setvar - set system variables
    tinker - modify sacred system parameters (dangerous)
    tos - modify service parameters
    trap - set trap address
    ttl - set time to live


    5 同步服务器的挑选标准


    3 Association Management:ntpv4中有不同的模式,

    ntp相关程序的参考帮助网站:http://www.eecis.udel.edu/~mills/ntp/html/ntpdc.html
    ntpq 命令查看:
    Run ntpq -p HOSTNAME, or one of the web-based utilities at 9.5. On-line Troubleshooting Utilities, to see the status of ntpd on HOSTNAME (without HOSTNAME the local host is queried). Check the official documentation for a detailed description of the ntpq utility (http://www.eecis.udel.edu/~mills/ntp/html/ntpq.html ). It will report something like this:
         remote           refid      st t when poll reach   delay   offset  jitter
    ==============================================================================
     ff05::101       .MCST.          16 u    -   64    0    0.000    0.000 4000.00
    *example.site.co .PPS.            1 u  320 1024  377    1.955   -1.234   1.368

    第一个特殊字母的意思:
    contains the "tally code" character. Short overview:
    * the source you are synchronized to (syspeer)
    o the PPS source if your ntpd (ppspeer, only if you have a PPS capable system and refclock)
    + candidate, i.e. it is considered a good source
    - outlyer, i.e. quality is not good enough
    x falseticker, i.e. this one is considered to distriute bad time
    See the Select field of the Peer status word on the NTP Event Messages and Status Words page for more information on the tally codes.

    remote :the hostname or IP of the remote machine.

    refid: the identification of the time source to which the remote machines is synced. May be (for example) a radio clock or another ntp server)

    st: the stratum of the remote machine. 16 is "unsynchronized". 0 is the best value, that could be (for example) a radio clock or the ntp servers private caesium clock (see http://www.eecis.udel.edu/~mills/ntp/html/index.html#intro for more information about ntp in general).

    when: how many seconds since the last poll of the remote machine.

    poll :the polling interval in seconds.

    reach :an 8-bit left-rotating register. Any 1 bit means that a "time packet" was received.

    delay :the time delay (in milliseconds) to communicate with the remote.

    offset :the offset (in milliseconds) between our time and that of the remote.

    jitter :the observed jitter (in milliseconds) of time with the remote.

    ntpdc
    格式:ntpdc [ -ilnps ] [ -c command ] [ host ] [ ... ]
    查询ntpd 关于当前状态,并要求修改状态。可以运行在交互模式和命令行模式。ntpd的几乎所有配置,都可以通过ntpdc在运行时来配置。
     
    ntptrace


    注意事项:
    1 不推荐使用 utpdate 来同步时间
    2 ntpd要尽早启动起来,在net和dns服务之后,在时间要求高的服务之前。
    3 避免DNS启动慢,应尽量使用同步源的IP Address,而不是域名。
    4 NTP中address分为4类:
     type     定义
     s ABC类单播地址
     b broadcast
     m multicast
     r 127.124.x.x

    疑问:
    1 通过ntpq命令,我们可以查看当前各个时间源服务器的状态已经当前主机在和谁进行同步。问题是,ntpd能否做到这点,会不会对一个时间有问题的源进行同步?
    2 目前我们NTP同步服务器网络部署情况?采取的拓扑结构?建议采用树形,并且同层同步的模式,这样更加稳定,即使上层服务器出问题,也可以减小影响。

    展开全文
  • NTP协议原理

    千次阅读 2018-01-23 16:06:53
    NTP协议

    什么是NTP协议

      当第一次听到NTP时,完全不知道是什么概念,只好问度娘。度娘搜到的答案如下:
    这里写图片描述

      看了度娘的解释后,才大概明白该协议是进行网络对时的协议,比如当自己的电脑时间不对,可以从另外一台电脑病基于NTP协议进行对时,以另外一台电脑的时间作为基准。那么,更官方的理解就是:使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用。对于运行NTP的本地系统,既可以接收来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以和其他设备互相同步。

    NTP工作原理

      NTP的基本工作原理如图所示。Device A和Device B通过网络相连,它们都有自己独立的系统时钟,需要通过NTP实现各自系统时钟的自动同步。为便于理解,作如下假设:
      在Device A和Device B的系统时钟同步之前,Device A的时钟设定为10:00:00am,Device B的时钟设定为11:00:00am。NTP报文在Device A和Device B之间单向传输所需要的时间为1秒。
    这里写图片描述
    1.Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该时间戳为10:00:00am(T1)。
    2.当此NTP报文到达Device B时,Device B加上自己的时间戳,该时间戳为11:00:01am(T2)。
    3.当此NTP报文离开Device B时,Device B再加上自己的时间戳,该时间戳为11:00:02am(T3)。
    4.当Device A接收到该响应报文时,Device A的本地时间为10:00:03am(T4)。
    5.至此,Device A已经拥有足够的信息来计算两个重要的参数:
    NTP报文的往返时延Delay=(T4-T1)-(T3-T2)=2秒。
    Device A相对Device B的时间差offset=((T2-T1)+(T3-T4))/2=1小时。

    NTP的报文格式

    这里写图片描述
    主要字段的解释如下:

    • LI(Leap Indicator):长度为2比特,值为”11”时表示告警状态,时钟未被同步。为其他值时NTP本身不做处理。

    这里写图片描述

    • VN(Version Number):长度为3比特,表示NTP的版本号,目前的最新版本为4。后面会有不同版本的测试,发现发送不同版本的报文,服务器均有数据返回,说明NTP协议是向下兼容的,老的版本也可以使用。

    • Mode:长度为3比特,表示NTP的工作模式。不同的值所表示的含义分别是:0未定义、1表示主动对等体模式、2表示被动对等体模式、3表示客户模式、4表示服务器模式、5表示广播模式或组播模式、6表示此报文为NTP控制报文、7预留给内部使用。
      这里写图片描述

    • Stratum:系统时钟的层数,取值范围为1~16,它定义了时钟的准确度。层数为1的时钟准确度最高,准确度从1到16依次递减,层数为16的时钟处于未同步状态,不能作为参考时钟。
      这里写图片描述
    • Poll:轮询时间,即两个连续NTP报文之间的时间间隔。
    • Precision:系统时钟的精度。
    • Root Delay:本地到主参考时钟源的往返时间。
    • Root Dispersion:系统时钟相对于主参考时钟的最大误差。
    • Reference Identifier:参考时钟源的标识。
    • Reference Timestamp:系统时钟最后一次被设定或更新的时间。
    • Originate Timestamp:NTP请求报文离开发送端时发送端的本地时间。
    • Receive Timestamp:NTP请求报文到达接收端时接收端的本地时间。
    • Transmit Timestamp:应答报文离开应答者时应答者的本地时间。
    • Authenticator:验证信息。
      这里写图片描述
      上述总结了NTP协议的原理,下一篇将讲解NTP的代码实现。
    展开全文
  • 易语言NTP协议源码

    2020-07-21 22:40:24
    易语言NTP协议源码,NTP协议,子程序1,数值转换,取时间标识,套接字_域名转地址,套接字_调试输出,创建,销毁,投递任务,启动线程_,创建进入许可证_,删除进入许可证_,WSAStartup,WSASocket,Connect,Send,CloseHandle,...
  • C语言ntp协议

    2016-01-18 19:15:04
    ntp协议示例程序,希望对ntp有兴趣的可以互相学习
  • NTP协议简介

    2014-09-03 18:33:57
    NTP协议的工作原理 应用 网络结构及实现模型 配置及常见故障排除
  • NTP 协议介绍

    2018-07-18 09:45:00
    NTP协议 NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步。NTP基于UDP报文进行传输,使用的UDP端口号为123。使用NTP的目的是对网络内...

    NTP协议

    NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步。NTP基于UDP报文进行传输,使用的UDP端口号为123。使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用。

    对于运行NTP的本地系统,既可以接收来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以和其他设备互相同步。

    NTP工作原理

    NTP的基本工作原理如图所示。Device A和Device B通过网络相连,它们都有自己独立的系统时钟,需要通过NTP实现各自系统时钟的自动同步。为便于理解,作如下假设:

    Device A和Device B的系统时钟同步之前,Device A的时钟设定为10:00:00am,Device B的时钟设定为11:00:00am。

    Device B作为NTP时间服务器,即Device A将使自己的时钟与Device B的时钟同步。

    NTP报文在Device A和Device B之间单向传输所需要的时间为1秒。

     

    系统时钟同步的工作过程如下:

    Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该时间戳为10:00:00am(T1)。

    当此NTP报文到达Device B时,Device B加上自己的时间戳,该时间戳为11:00:01am(T2)。

    当此NTP报文离开Device B时,Device B再加上自己的时间戳,该时间戳为11:00:02am(T3)。

    Device A接收到该响应报文时,Device A的本地时间为10:00:03am(T4)。

    至此,Device A已经拥有足够的信息来计算两个重要的参数:

    NTP报文的往返时延Delay=(T4-T1)-(T3-T2)=2秒。

    Device A相对Device B的时间差offset=((T2-T1)+(T3-T4))/2=1小时。

    这样,Device A就能够根据这些信息来设定自己的时钟,使之与Device B的时钟同步。

     

    NTP的报文格式

    NTP有两种不同类型的报文,一种是时钟同步报文,另一种是控制报文。控制报文仅用于需要网络管理的场合,它对于时钟同步功能来说并不是必需的。

     

    主要字段的解释如下:

    LI(Leap Indicator):为2比特,值为“11”时表示告警状态,时钟未被同步。为其他值时NTP本身不做处理。

    VN(Version Number):长度为3比特,表示NTP的版本号。

    Mode:长度为3比特,表示NTP的工作模式。不同的值所表示的含义分别是:0未定义、1表示主动对等体模式、2表示被动对等体模式、3表示客户模式、4表示服务器模式、5表示广播模式或组播模式、6表示此报文为NTP控制报文、7预留给内部使用。

    Stratum:系统时钟的层数,取值范围为1~16,它定义了时钟的准确度。层数为1的时钟准确度最高,准确度从1到16依次递减,层数为16的时钟处于未同步状态,不能作为参考时钟。

    Poll:轮询时间,即两个连续NTP报文之间的时间间隔。

    Precision:系统时钟的精度。

    Root Delay:本地到主参考时钟源的往返时间。

    Root Dispersion:系统时钟相对于主参考时钟的最大误差。

    Reference Identifier:参考时钟源的标识。

    Reference Timestamp:系统时钟最后一次被设定或更新的时间。

    Originate Timestamp:NTP请求报文离开发送端时发送端的本地时间。

    Receive Timestamp:NTP请求报文到达接收端时接收端的本地时间。

    Transmit Timestamp:应答报文离开应答者时应答者的本地时间。

    Authenticator:验证信息。

    参考:https://www.cnblogs.com/panhongqing/p/6292348.html

    转载于:https://www.cnblogs.com/tunian/p/9327460.html

    展开全文
  • ntp ntp协议

    2019-01-10 16:46:35
    在维护网络设备或者linux系统设备的时候,时间同步是非常重要的,如应用程序服务,...请求报文:ntp基于UDP协议传输,应用端口是123端口。 其中LI(Leap Indicator):长度为2比特,值为"11"时表示告警状态,时钟...
  • 易语言源码易语言NTP协议源码.rar
  • NTP协议Demo程序

    热门讨论 2011-11-12 20:02:21
    1,本Demo程序模拟NTP协议,实现从客户端向服务端发送NTP请求,进行时钟同步的操作。 2,使用了Base64编解码对NTP消息包进行打包,解包。 3,在VC2005环境下测试通过。
  • NTP协议规范简介分析

    2012-11-14 23:07:55
    NTP协议规范简介分析
  • linux 上ntp协议实现

    2013-07-04 20:11:48
    基于linux上C语言开发的NTP协议。源码及文档。
  • NTP协议实现

    千次阅读 2013-06-28 18:00:42
    10.4 实验内容 ——NTP协议实现 1.实验目的  通过实现NTP协议的练习,进一步掌握Linux网络编程,并且提高协议的分析与实现能力,为参与完成综合性项目打下良好的基础。 2.实验内容  Network Time Protocol...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,100
精华内容 840
关键字:

ntp协议