等雨成冰的个人主页

http://www.qtcn.org/bbs/u/130507  [收藏] [复制]

等雨成冰

不求与人相比,但求超越自己。

  • 8

    关注

  • 6

    粉丝

  • 43

    访客

  • 等级:新手上路
  • 总积分:8
  • 保密,2011-01-01

最后登录:2016-09-09

更多资料

日志

类NTP服务器的一段代码

2016-07-08 18:08
关于类NTP服务器的一段代码,用于同步平台和nvr的时间。望大家不吝赐教:
  1. #include <stdio.h>
    #include <stdlib.h>
    #include <WinSock2.h>
    #include <time.h>
    #include <stdio.h>
    #define  int8      char
    #define  uint8     unsigned char
    #define  uint32    unsigned int
    #define  ulong32   unsigned long
    #define  long32    long
    #define  int32     int
    #define  long64    long long
    #pragma comment( lib, "ws2_32.lib")
    #define  NTPPORT  9966
    typedef struct NTPPACKET
    {
      uint8     li_vn_mode;
      uint8     stratum;
      uint8     poll;
      uint8     precision;
      ulong32   root_delay;
      ulong32   root_dispersion;
      int8           ref_id[4];
      ulong32   reftimestamphigh;
      ulong32   reftimestamplow;
      ulong32   oritimestamphigh;
      ulong32   oritimestamplow;
      ulong32   recvtimestamphigh;
      ulong32   recvtimestamplow;
      ulong32   trantimestamphigh;
      ulong32   trantimestamplow;
    }NTPPacket;
    NTPPacket  recvPack,sendPack;
    //定义为long64,解决32位数的符号位问题
    long64   recvtimestamphigh = 0,timeSpace = 0x83aa7e80U; //3600s*24h*(365days*70years+17days)
    void CombineNTPPackage()
    {
      memset(&sendPack,0,sizeof(sendPack));
      sendPack.li_vn_mode=0x1b;
      recvtimestamphigh= timeSpace+time(NULL); //设置发往客户端的时间戳, 0x83aa7e80U 是1900年到1970总共的秒数,由于time(time_t *time)只能算出1970到今天的总共时间(秒)  NTP时间同步报文中包含的时间是格林威治时间,是从1900年开始计算的秒数
      sendPack.recvtimestamphigh = htonl(recvtimestamphigh);
    }
    int main()
    {
        WSADATA wsaData;
        WORD sockVer = MAKEWORD(2, 2);
        WSAStartup(sockVer, &wsaData);
        int32  sockfd = -1;
        struct sockaddr_in servaddr, clientAddr;
        if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0){
            perror("create socket error!\n");
            return -1;
        }
        memset(&servaddr, 0,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(NTPPORT);
        if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
            perror("bind error");
            return -1;
        }
        int ret = -1;
        int len = sizeof(clientAddr);
        time_t sTime,eTime;
        while(1)
        {
            ret = recvfrom(sockfd, (char*)&recvPack, sizeof(recvPack), 0, (struct sockaddr *)&clientAddr,&len );
            if(ret>0){
                sTime = time(NULL);
                CombineNTPPackage();
                eTime = time(NULL);
                sendPack.trantimestamphigh = timeSpace+eTime+eTime-sTime;
                if(sendto(sockfd,(char*)&sendPack,sizeof(sendPack),0,(struct sockaddr *)&clientAddr,sizeof(struct sockaddr))<0){
                    perror("sendto data  error!\n");
                }
            }else {
                perror("recvfrom socket error!\n");
                if(0 == ret) break;
                Sleep(100);
                continue;
            }
            Sleep(10000);
        }
        closesocket(sockfd);
        WSACleanup( );
    }

注:
1,NTP协议算时间差:
        客户机跟服务器的时间差=((T2-T1)+(T3-T4))>>1
        T1是客户端的时间戳  :recvPack.oritimestamphigh;
        T2是服务器自身的时间戳  :sendPack.recvtimestamphigh
        T3是服务器处理过后发往客户端的时间戳 :newpack.trantimestamphigh
        T4是客户端收到数据的时候的时间戳:finaltimes= time(NULL)+timeSpace
  1. difftime=((sendPack.recvtimestamphigh-recvPack.oritimestamphigh)+(newpack.trantimestamphigh-finaltimes))>>1;

2,客户端算延时:
  1. delaytime=((sendPack.recvtimestamphigh-recvPack.oritimestamphigh)-(sendPack.trantimestamphigh-finaltimes))>>1;

3,客户端算真正时间的时间戳:
  1. struct timeval tv1  tv1.tv_sec=time(NULL)+difftime+delaytime;
    tv1.tv_usec=0;

分类:NTP|回复:0|浏览:1332|全站可见|转载
 

Powered by phpwind v8.7 Certificate Copyright Time now is:05-19 04:34
©2005-2016 QTCN开发网 版权所有 Gzip disabled