Chinaunix首页 | 论坛 | 博客
  • 博客访问: 74620
  • 博文数量: 15
  • 博客积分: 85
  • 博客等级: 民兵
  • 技术积分: 136
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-31 10:32
文章分类

全部博文(15)

文章存档

2014年(1)

2013年(1)

2012年(13)

我的朋友

分类: LINUX

2014-02-12 15:46:20


虽然说原理上并不难,但是过程中却也遇到了些问题。重要的是,做完这个实验之后,搞清了一些平时并不太注意的东西。


另外,只计算了整数部分,小数部分没有计算。校正后的时间跟标准时间误差不超过一秒。

接下来复习并总结一下前一阵学过的内容,并且准备拟定下一个阶段的计划。

//colinluan 090613
//GMT时间:格林威治时间,国际标准时间,中国位于东八区,时间为GMT+8
//UTC时间: 通用协调时间,可以认为跟GMT是一个概念。
//时间戳:NTP服务器上的时间戳为从1900年1月1日0时0分开始到至今的秒数(UTC时间)
//    而PC机上的时间戳为1970年1月1日0时0分到至今的秒数(程序中的time(NULL)返回的是UTC时间)
//    所以,要对PC机的时间戳与服务器时间戳计算时,需在PC机的时间戳基础上加上1900-1970的秒数 3600s*24h*(365days*70years+17days)
//    客户机跟服务器的时间差=((T2-T1)+(T3-T4))>>1
//    传输延时=((T2-T1)-(T3-T4))>>1 (假设来跟去的传输延时是一样的)
//    T1 请求离开客户端的时间戳
//    T2 请求到达服务器的时间戳(由服务器返回)
//    T3 从服务器返回的时间戳(由服务器返回)
//    T4 返回数据包到达客户端的时间戳
//  客户端(请求)          服务器
//    T1 ---------------------------------> T2
//              (返回)
//    T4 <--------------------------------- T3
//    在计算时由于会碰到32位数的符号位问题,索性用64位数进行计算。

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. //#include <netdb.h>
  6. #include <sys/socket.h>
  7. #include <sys/types.h>
  8. #include <sys/time.h>
  9. #include <unistd.h>

  10. #define int8 char
  11. #define uint8 unsigned char
  12. #define uint32 unsigned int
  13. #define ulong32 unsigned long
  14. #define long32 long
  15. #define int32 int
  16. #define long64 long long

  17. #define debug

  18. //3600s*24h*(365days*70years+17days)
  19. #define From00to70 0x83aa7e80U

  20. #define NTPSVR1 "132.163.4.102" //USA
  21. #define NTPSVR2 "132.163.135.132" //USA
  22. #define NTPSVR3 "192.53.103.103" //Germany

  23. #define NTPPORT 123
  24. typedef struct NTPPACKET
  25. {
  26.   uint8 li_vn_mode;
  27.   uint8 stratum;
  28.   uint8 poll;
  29.   uint8 precision;
  30.   ulong32 root_delay;
  31.   ulong32 root_dispersion;
  32.   int8 ref_id[4];
  33.   ulong32 reftimestamphigh;
  34.   ulong32 reftimestamplow;
  35.   ulong32 oritimestamphigh;
  36.   ulong32 oritimestamplow;
  37.   ulong32 recvtimestamphigh;
  38.   ulong32 recvtimestamplow;
  39.   ulong32 trantimestamphigh;
  40.   ulong32 trantimestamplow;
  41. }NTPPacket;

  42. NTPPacket ntppack,newpack;

  43. //定义为long64,解决32位数的符号位问题
  44. long64 firsttimestamp,finaltimestamp;
  45. long64 diftime,delaytime;

  46. void NTP_Init()
  47. {
  48.   bzero(&ntppack,sizeof(ntppack));
  49.   ntppack.li_vn_mode=0x1b;//0|(3<<2)|(3<<5);
  50.   //获取初始时间戳T1
  51.   firsttimestamp=From00to70+time(NULL);//-8*3600;
  52.   ntppack.oritimestamphigh=htonl(firsttimestamp);
  53. }
  54. int main()
  55. {
  56. // ulong32 clienttime;
  57. // ulong32 diftime,firsttimestamp,finaltimestamp;
  58.   fd_set inset1;
  59.   int32 sockfd;
  60.   struct timeval tv,tv1;
  61.   struct timezone tz;
  62.   struct sockaddr_in addr;
  63. // printf("%d,%d,%d\n",&ntppack.li_vn_mode,&ntppack.stratum,&ntppack.poll);
  64. // printf("%d %ld\n",sizeof(NTPPacket),sizeof(ntppack));
  65.   
  66. // printf("%ld\n",time(NULL));
  67.   
  68.   if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
  69.     {
  70.       perror("create socket error!\n");
  71.       exit(1);
  72.     }
  73.   
  74.   addr.sin_family=AF_INET; //IPV4协议
  75.   addr.sin_port =htons(NTPPORT); //NTP专用的123端口
  76.   addr.sin_addr.s_addr=inet_addr(NTPSVR1); //校时服务器
  77.   bzero(&(addr.sin_zero),8); //清零
  78.   
  79.   //wait 5s
  80.   tv.tv_sec=10; //select等待时间为10S
  81.   tv.tv_usec=0;
  82.   
  83.   FD_ZERO(&inset1);
  84.   FD_SET(sockfd,&inset1);
  85.   
  86.   NTP_Init();
  87.   //发送数据请求包
  88.   sendto(sockfd,&ntppack,sizeof(ntppack),0,(struct sockaddr *)&addr,sizeof(struct sockaddr));
  89.   //select巡视
  90.   if(select(sockfd+1,&inset1,NULL,NULL,&tv)<0)
  91.   {
  92.     perror("select error!\n");
  93.     exit(1);
  94.   }
  95.   else
  96.   {
  97.   //printf("OK\n");
  98.     if(FD_ISSET(sockfd,&inset1))
  99.     {
  100.   // printf("OK\n");
  101.      if(recv(sockfd,&newpack,sizeof(newpack),0)<0) //接收数据在newpack中。
  102.      {
  103.       perror("recv error!\n");
  104.       exit(1);
  105.      }
  106.     }
  107.   }
  108.   //到达客户机时间戳T4
  109.   finaltimestamp=time(NULL)+From00to70;//-8*3600;
  110.   
  111.   //将网络上传送的大端数据改为小端形式。
  112.  newpack.root_delay= ntohl(newpack.root_delay);
  113.  newpack.root_dispersion= ntohl(newpack.root_dispersion);
  114.  newpack.reftimestamphigh=ntohl(newpack.reftimestamphigh);
  115.  newpack.reftimestamplow= ntohl(newpack.reftimestamplow);
  116.  newpack.oritimestamphigh= ntohl(newpack.oritimestamphigh);
  117.  newpack.oritimestamplow= ntohl(newpack.oritimestamplow);
  118.  newpack.recvtimestamphigh= ntohl(newpack.recvtimestamphigh);
  119.  newpack.recvtimestamplow= ntohl(newpack.recvtimestamplow);
  120.  newpack.trantimestamphigh= ntohl(newpack.trantimestamphigh);
  121.  newpack.trantimestamplow= ntohl(newpack.trantimestamplow);
  122.  
  123.  //求出客户机跟服务器的时间差=((T2-T1)+(T3-T4))/2
  124.  diftime=((newpack.recvtimestamphigh-firsttimestamp)+(newpack.trantimestamphigh-finaltimestamp))>>1;
  125.  //求出延时
  126.  delaytime=((newpack.recvtimestamphigh-firsttimestamp)-(newpack.trantimestamphigh-finaltimestamp))>>1;
  127.  //diftime=(5-9)>>1;

  128.  //求出真正时间的时间戳
  129.  tv1.tv_sec=time(NULL)+diftime+delaytime;
  130.  tv1.tv_usec=0;
  131.  //tz.

  132.  #ifdef debug
  133.   printf("\n\ndebug information ...\n\n");
  134.   printf("time(NULL) is %ld\n",time(NULL));
  135.   printf("different time is %ld\n",diftime);
  136.   printf("delaytime is %ld\n",delaytime);
  137.   printf("time(NULL)+diftime+delaytime=%ld\n",time(NULL)+diftime+delaytime);
  138.   printf("tv1.tv_sec is %ld\n\n", tv1.tv_sec);
  139.  #endif
  140.   
  141.   settimeofday(&tv1,NULL);
  142. //diftime=diftime-From00to70;

  143.  #ifdef debug
  144.   //printf("different time is %ld\n",diftime);
  145.   printf("delay time is %ld\n",delaytime);
  146.   //printf("firsttimestamp is %x\n",time(NULL));
  147.   printf("newpack.tran is %ld\n",newpack.trantimestamphigh);
  148.   printf("newpack.recv is %ld\n",newpack.recvtimestamphigh);
  149.   printf("firsttimestamp is %ld\n",firsttimestamp);
  150.   printf("finaltimestamp is %ld\n",finaltimestamp);
  151.   printf("newpack.recv-firsttimestamp is %ld\n",newpack.recvtimestamphigh-firsttimestamp);
  152.   printf("newpack.tran-finaltimestamp is %ld\n",newpack.trantimestamphigh-finaltimestamp);
  153.   printf("(recv-first)+(ftran-final) is %ld\n",(newpack.recvtimestamphigh-firsttimestamp)+(newpack.trantimestamphigh-finaltimestamp));
  154.   printf("((recv-first)+(ftran-final))>>1 is %ld\n",((newpack.recvtimestamphigh-firsttimestamp)+(newpack.trantimestamphigh-finaltimestamp))>>1);
  155.   printf("different time is %ld\n\n",diftime);
  156.   printf("sizeof(long long) is:%d\n",sizeof(long long));
  157.   printf("Current time is...\n");
  158.   system("date");
  159.  #endif
  160. }
注:原文代码59行和117行错误已修改,目前可以编译通过并成功运行。

转自:
阅读(5011) | 评论(0) | 转发(2) |
0

上一篇:Linux进程-命令行参数和环境列表

下一篇:没有了

给主人留下些什么吧!~~