加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
ntp2.c 6.04 KB
一键复制 编辑 原始数据 按行查看 历史
jin 提交于 2024-07-15 16:06 . add demos
#include <netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<time.h>
#include<stdint.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<unistd.h>
#include<errno.h>
//可用的NTP地址:202.112.31.197(time.edu.cn)还有很多可用的
#define gap_1900_1970 0x83aa7e80
//NTP时间从1970开始 比我们计算机常用的UTC早 秒数更多
#define USEC_TO_UINT32(x) ((uint32_t)(((uint64_t)(x)<<32)/1000000))
//将微妙整数转化为小数秒
#define UINT32_TO_USEC(x) ((uint32_t)(((double)ntohl(x)/((uint64_t)1<<32))*1000000))
//将网络字节序转化为主机字节序 小数秒转化为微秒整数
typedef struct _uint64_time
{
uint32_t int_part;
uint32_t float_part;
} uint64_time;
typedef struct _NTP_time
{
unsigned char leap_ver_mode;
unsigned char stratum;
char poll;
char precision;
int32_t root_delay;
int32_t root_dispersion;
int32_t reference_identifine;
uint64_time reference_time;
uint64_time original_time;
uint64_time receive_time;
uint64_time transmit_time;
} NTP_time, *NTP_time_Ptr;
void get_NTP(NTP_time *ntp_time);
void print_NTP(NTP_time* ntp_time);
float get_offset(NTP_time *ntp_time);
void set_localtime(float offset);
int main(int argc,char *argv[])
{
NTP_time ntp_time;
int socket_fd,sendtypes,recvtypes,pton_temp = 0,select_temp;
struct sockaddr_in server_addr;
unsigned char recvbuf[48] = {0x00};
if(argc!=2)
{
printf("main parameters is wrong! please use 2!\n");
exit(EXIT_FAILURE);
}
get_NTP(&ntp_time);
socket_fd = socket(AF_INET,SOCK_DGRAM,0);
if(socket_fd == -1)
{
perror("Socket failed");
exit(EXIT_FAILURE);
}
memset(&server_addr,0x00,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(123);
pton_temp = inet_pton(AF_INET,argv[1],&server_addr.sin_addr);
if(pton_temp!=1)
{
perror("Pton failed");
exit(EXIT_FAILURE);
}
sendtypes = sendto(socket_fd,&ntp_time,sizeof(NTP_time),0,(struct sockaddr *)&server_addr,sizeof(server_addr));
if(sendtypes == -1)
{
perror("Sendto failed");
close(socket_fd);
exit(EXIT_FAILURE);
}
fd_set read_fds;
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;//设置超时时间1s
FD_ZERO(&read_fds);
FD_SET(socket_fd, &read_fds);
select_temp = select(socket_fd + 1, &read_fds, NULL, NULL, &timeout);
if(select_temp > 0)
{
recvtypes = recvfrom(socket_fd,recvbuf,sizeof(recvbuf),0,NULL,NULL);
if(recvtypes == -1)
{
perror("Recvfrom failed");
close(socket_fd);
exit(EXIT_FAILURE);
}
NTP_time_Ptr ntp_time_ptr = (NTP_time_Ptr)(recvbuf);
(void)print_NTP(ntp_time_ptr);
float offset = get_offset(ntp_time_ptr);
printf("offset = %f\n", offset);
set_localtime(offset);
}
else
{
perror("select:no data!");
close(socket_fd);
exit(EXIT_FAILURE);
}
close(socket_fd);
return 0;
}
void get_NTP(NTP_time *ntp_time)
{
struct timeval tv;
memset(ntp_time,0x00,sizeof(NTP_time));
ntp_time->leap_ver_mode = 0x1b;
ntp_time->stratum = 0;
ntp_time->poll = 4;
ntp_time->precision = -6;
gettimeofday(&tv, NULL);
ntp_time->transmit_time.int_part = htonl(tv.tv_sec + gap_1900_1970);
ntp_time->transmit_time.float_part = htonl(USEC_TO_UINT32(tv.tv_usec));
printf("now tv_sec: %ld\n", tv.tv_sec);
printf("now tv_usec: %ld\n", tv.tv_usec);
}
void print_NTP(NTP_time* ntp_time)
{
printf("leap_ver_mode: %x\n",ntp_time->leap_ver_mode);
printf("stratum: %d\n",ntp_time->stratum);
printf("poll: %d\n",ntp_time->poll);
printf("precision: %d\n",ntp_time->precision);
printf("reference time: %us %dms\n",ntohl(ntp_time->reference_time.int_part)-gap_1900_1970,UINT32_TO_USEC(ntp_time->reference_time.float_part)/1000);
printf("original time: %us %dms\n",ntohl(ntp_time->original_time.int_part)-gap_1900_1970,UINT32_TO_USEC(ntp_time->original_time.float_part)/1000);
printf("receive time: %us %dms\n",ntohl(ntp_time->receive_time.int_part)-gap_1900_1970,UINT32_TO_USEC(ntp_time->receive_time.float_part)/1000);
printf("transmit time: %us %dms\n",ntohl(ntp_time->transmit_time.int_part)-gap_1900_1970,UINT32_TO_USEC(ntp_time->transmit_time.float_part)/1000);
}
float get_offset(NTP_time *ntp_time)
{
// uint32_t sec = 0;
// uint32_t usec = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
uint32_t sec1 = ntohl(ntp_time->original_time.int_part) - gap_1900_1970;
uint32_t usec1 = UINT32_TO_USEC(ntp_time->original_time.float_part);
double t1 = sec1 * 1.0 + usec1 / 1000000.;
// printf("t1 = %f usec1: %f\n", t1, sec1 + usec1 / 1000000.);
printf("t1 = %f sec1: %u, usec1: %u\n", t1, sec1, usec1);
uint32_t sec2 = ntohl(ntp_time->receive_time.int_part) - gap_1900_1970;
uint32_t usec2 = UINT32_TO_USEC(ntp_time->original_time.float_part);
double t2 = sec2 + usec2 / 1000000.;
printf("t2 = %f sec2: %u, usec2: %u\n", t2, sec2, usec2);
uint32_t sec3 = ntohl(ntp_time->transmit_time.int_part) - gap_1900_1970;
uint32_t usec3 = UINT32_TO_USEC(ntp_time->transmit_time.float_part);
double t3 = sec3 + usec3 / 1000000.;
printf("t3 = %f sec3: %u, usec3: %u\n", t3, sec3, usec3);
double t4 = tv.tv_sec + tv.tv_usec / 1000000.;
printf("t4 = %f\n", t4);
return ((t2 - t1) + (t3 - t4)) / 2;
}
void set_localtime(float offset)
{
struct timeval tv;
gettimeofday(&tv, NULL);
if (tv.tv_usec + (offset - (int)offset) * 1000000 >= 1000000) {
tv.tv_usec += (offset - (int)offset) * 1000000 - 1000000;
tv.tv_sec += (int)offset + 1;
}
else {
tv.tv_usec += (offset - (int)offset) * 1000000;
tv.tv_sec += (int)offset;
}
struct tm *local = localtime((time_t *)&tv.tv_sec);
char buf[32] = {0};
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", local);
printf("new time: %s\n", buf);
// settimeofday(const struct timeval *tv, const struct timezone *tz)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化