单播SNTP客户端

举报
aiot_bigbear 发表于 2022/09/25 04:11:35 2022/09/25
【摘要】 一、功能实现 以NTP服务器为基准,同步网内计算机或嵌入式设备的时间。 二、协议原理 协议: 客户端向NTP服务器发送请求数据包,NTP服务器回应一个数据包。 分别记录客户端发送请求包时的时刻t1和接收到回应包的时刻t4,服务器回应的数据包内包含了服务器接收到请求包的时刻t2和服务器发送回应包的时刻t3。 t...

一、功能实现

以NTP服务器为基准,同步网内计算机或嵌入式设备的时间。

二、协议原理

协议:

客户端向NTP服务器发送请求数据包,NTP服务器回应一个数据包。

分别记录客户端发送请求包时的时刻t1和接收到回应包的时刻t4,服务器回应的数据包内包含了服务器接收到请求包的时刻t2和服务器发送回应包的时刻t3。

t4-t1表示整个消息传递过程所需要的时间;

t3-t2表消息传递过程在服务器停留的时间

(t4-t1)-(t3-t2)是来回路上消耗的时间如果来回传输所用的时间一样,那么,单程的时间为

t = ( (t4 - t1) - (t3 - t2) )/2;

假定客户端相对于服务器的时间误差是dis,则有下列等式:

t2 = t1 + dis + t;

t4 = t3 - dis + t;

则:dis = (( t2 - t1 ) + ( t3 - t4 )) / 2;

根据此差值重新设置时间即可。

说明:

服务器发返回的时间是以1900年为基准计算的,而linux是以1970年为基准的,所以需要用到一个常数做转化:

#define JAN_1970   2208988800UL        /* 1970 - 1900 in seconds */

在计算与服务器的差值时会用到此值。

三、代码实现

ntp.h

  1. #ifndef __NTP_H  
  2. #define __NTP_H  
  3.   
  4. #define JAN_1970    2208988800UL        /* 1970 - 1900 in seconds */  
  5. #define NTP_SERVER_NAME "10.13.0.21"    //my windows 7 ntp server  
  6. #define NTP_PORT    123  
  7.   
  8. /* some ntp server 
  9. time-a.nist.gov 
  10. time-b.nist.gov 
  11. time-a.timefreq.bldrdoc.gov 
  12. time-b.timefreq.bldrdoc.gov 
  13. time-c.timefreq.bldrdoc.gov 
  14. utcnist.colorado.edu 
  15. ntp.tuxfamily.net 
  16. time-nw.nist.gov 
  17. nist1.datum.com 
  18. nist1-ny.glassey.com 
  19. nist1.aol-ca.truetime.com 
  20. ntp2.belbone.be 
  21. ntp.doubleukay.com 
  22. ntp0.cs.mu.OZ.AU 
  23. time.apple.com 
  24. 0.pool.ntp.org 
  25. 1.pool.ntp.org 
  26. 2.pool.ntp.org 
  27. 2.europe.pool.ntp.org 
  28. 3.europe.pool.ntp.org 
  29. 1.north-america.pool.ntp.org 
  30. 2.north-america.pool.ntp.org 
  31. 0.oceania.pool.ntp.org 
  32. 1.oceania.pool.ntp.org 
  33. 0.au.pool.ntp.org 
  34. 3.au.pool.ntp.org 
  35. */  
  36.   
  37. typedef struct    
  38. {  
  39.     unsigned char LiVnMode;  
  40.     unsigned char Stratum;  
  41.     unsigned char Poll;  
  42.     unsigned char Precision;  
  43.     long int RootDelay;  
  44.     long int RootDispersion;  
  45.     char RefID[4];  
  46.     long int RefTimeInt;  
  47.     long int RefTimeFraction;  
  48.     long int OriTimeInt;  
  49.     long int OriTimeFraction;  
  50.     long int RecvTimeInt;  
  51.     long int RecvTimeFraction;  
  52.     long int TranTimeInt;  
  53.     long int TranTimeFraction;  
  54. }STNP_Header;  
  55.   
  56. int SYNC_Time(void);  
  57.   
  58. #endif  
ntp.c

  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <string.h>  
  4. #include <time.h>  
  5. #include <sys/time.h>  
  6. #include <netinet/in.h>  
  7. #include <sys/socket.h>  
  8. #include <arpa/inet.h>  
  9. #include <netdb.h>  
  10. #include "sntp.h"  
  11.   
  12. int gethostIPbyname(char *name)  
  13. {  
  14.     struct hostent *host=NULL;  
  15.     struct in_addr *addr=NULL;  
  16.   
  17.     host = gethostbyname (name);  
  18.     if(host->h_addr == NULL)  
  19.         return -1;  
  20.     addr = (struct in_addr*)host->h_addr;  
  21.       
  22.     return addr->s_addr;  
  23. }  
  24.   
  25. int GetNTPTime(STNP_Header *H_SNTP)  
  26. {  
  27.     int sockfd=0;  
  28.     struct sockaddr_in server;  
  29.       
  30.     bzero((void*)H_SNTP, sizeof(STNP_Header));  
  31.     H_SNTP->LiVnMode = 0x1b;  
  32.       
  33.     server.sin_family = AF_INET;  
  34.     server.sin_addr.s_addr = gethostIPbyname(NTP_SERVER_NAME);  
  35.     server.sin_port = htons(NTP_PORT);  
  36.     if(-1 == (int)server.sin_addr.s_addr)  
  37.         return -1;  
  38.       
  39.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  40.     if(sockfd<0)  
  41.     {  
  42.         perror("sockfd");  
  43.         return -1;  
  44.     }  
  45.     if(sendto(sockfd, (void*)H_SNTP, sizeof(STNP_Header), 0, (struct sockaddr*)&server, sizeof(server))<0)  
  46.     {  
  47.         perror("sendto");  
  48.         return -1;  
  49.     }  
  50.       
  51.     fd_set r;  
  52.     FD_ZERO(&r);  
  53.     FD_SET(sockfd, &r);  
  54.     struct timeval timeout;  
  55.     timeout.tv_sec = 5;  
  56.     timeout.tv_usec = 0;  
  57.       
  58.     if(1 != select(sockfd+1, &r, NULL, NULL, &timeout))  
  59.         return -1;  
  60.     if(recv(sockfd, (void*)H_SNTP, sizeof(STNP_Header), 0)<0)  
  61.         return -1;  
  62.       
  63.     close(sockfd);  
  64.     return 0;  
  65. }  
  66.   
  67. int SYNC_Time(void)  
  68. {  
  69.     STNP_Header HeaderSNTP;  
  70.     time_t t1,t2,t3,t4,dis;  
  71.       
  72.     time(&t1);  
  73.     t1+=JAN_1970;  
  74.       
  75.     printf("sync time from %s\n", NTP_SERVER_NAME);  
  76.     if(GetNTPTime(&HeaderSNTP)<0)  
  77.         return -1;  
  78.           
  79.     time(&t4);  
  80.     t4+=JAN_1970;  
  81.       
  82.     t2 = ntohl(HeaderSNTP.RecvTimeInt);  
  83.     t3 = ntohl(HeaderSNTP.TranTimeInt);  
  84.       
  85.     dis = ( (t2-t1)+(t3-t4) )/2;  
  86.     if(dis<=0)  
  87.         printf("local time is faster then server %d seconds\n", (int)-dis);  
  88.     else  
  89.         printf("local time is slower then server %d seconds\n", (int)dis);  
  90.       
  91.     struct timeval tv;  
  92.     gettimeofday (&tv, 0);  
  93.     tv.tv_sec+=dis;  
  94.     printf("%s", ctime(&tv.tv_sec));  
  95.       
  96.     settimeofday (&tv, NULL);  
  97.       
  98.     return 0;  
  99. }  
main.c

  1. #include <stdio.h>  
  2. #include "sntp.h"  
  3.   
  4. int main(void)  
  5. {  
  6.     if(SYNC_Time()<0)  
  7.         printf("sync time Failed!\n");  
  8.     printf("sync time Succeed!\n");  
  9.       
  10.     return 0;  
  11. }  

文章来源: blog.csdn.net,作者:悟空胆好小,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/xushx_bigbear/article/details/45054801

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。