当前仓库属于暂停状态,部分功能使用受限,详情请查阅 仓库状态说明
1 Star 8 Fork 8

xietong / ntp_time
暂停

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ntp_time.c 6.75 KB
一键复制 编辑 原始数据 按行查看 历史
/********************************************************************************
源代码来自网络,经本人精简ntp部分,供大家参考
*********************************************************************************/
#include "ntp_time.h"
int send_packet(int fd)
{
unsigned int data[12];
int ret;
struct timeval now;
if (sizeof(data) != 48)
{
PDEBUG("data 长度小于48!");
exit(1);
}
memset((char *)data, 0, sizeof(data));
data[0] = htonl((LI << 30) | (VN << 27) | (MODE << 24) | (STRATUM << 16) | (POLL << 8) | (PREC & 0xff));
data[1] = htonl(1 << 16);
data[2] = htonl(1 << 16);
//获得本地时间
gettimeofday(&now, NULL);
data[10] = htonl(now.tv_sec + JAN_1970);
data[11] = htonl(NTPFRAC(now.tv_usec));
ret = send(fd, data, 48, 0);
PDEBUG("发送请求数据包到服务器, ret: %d\n", ret);
}
int get_server_time(int sock, struct timeval *newtime)
{
int ret;
unsigned int data[12];
NtpTime oritime, rectime, tratime, destime;
struct timeval offtime, dlytime;
struct timeval now;
bzero(data, sizeof(data));
ret = recvfrom(sock, data, sizeof(data), 0, NULL, 0);
if (ret == -1)
{
PDEBUG("读取返回数据失败\n");
exit(1);
}
else if (ret == 0)
{
PDEBUG("读取到速度长度: 0!\n");
return 1;
}
//1970逆转换到1900
gettimeofday(&now, NULL);
destime.integer = now.tv_sec + JAN_1970;
destime.fraction = NTPFRAC(now.tv_usec);
//字节序转换
oritime.integer = DATA(6);
oritime.fraction = DATA(7);
rectime.integer = DATA(8);
rectime.fraction = DATA(9);
tratime.integer = DATA(10);
tratime.fraction = DATA(11);
//Originate Timestamp T1 客户端发送请求的时间
//Receive Timestamp T2 服务器接收请求的时间
//Transmit Timestamp T3 服务器答复时间
//Destination Timestamp T4 客户端接收答复的时间
//网络延时 d 和服务器与客户端的时差 t
//d = (T2 - T1) + (T4 - T3); t = [(T2 - T1) + (T3 - T4)] / 2;
long long orius, recus, traus, desus, offus, dlyus;
orius = TTLUSEC(MKSEC(oritime), MKUSEC(oritime));
recus = TTLUSEC(MKSEC(rectime), MKUSEC(rectime));
traus = TTLUSEC(MKSEC(tratime), MKUSEC(tratime));
desus = TTLUSEC(now.tv_sec, now.tv_usec);
offus = ((recus - orius) + (traus - desus)) / 2;
dlyus = (recus - orius) + (desus - traus);
offtime.tv_sec = GETSEC(offus);
offtime.tv_usec = GETUSEC(offus);
dlytime.tv_sec = GETSEC(dlyus);
dlytime.tv_usec = GETUSEC(dlyus);
struct timeval new;
//粗略校时
//new.tv_sec = tratime.integer - JAN_1970;
//new.tv_usec = USEC(tratime.fraction);
//精确校时
new.tv_sec = destime.integer - JAN_1970 + offtime.tv_sec;
new.tv_usec = USEC(destime.fraction) + offtime.tv_usec;
//提取现在好的时间
*newtime = new;
return 0;
}
/*
* 更新本地时间
* @newtime -- 要新的时间
* */
int mod_localtime(struct timeval newtime)
{
//设置方式1
#if 1
//只有 root 用户拥有修改时间的权限
if (getuid() != 0 && geteuid() != 0)
{
PDEBUG("不是 root 用户,无法进行时间校准,被迫终止 !\n");
exit(1);
}
if (settimeofday(&newtime, NULL) == -1)
{
PDEBUG("设置时间失败 !\n");
return -1;
}
else
{
PDEBUG("设置时间成功 !\n");
}
#endif
//设置方式2(对于settimeofday函数不可用情况)
#if 1
struct tm *tm_p;
char time_buff[100];
memset(time_buff, 0, 100);
time_t time_sec = newtime.tv_sec + 28800;
tm_p = gmtime(&time_sec);
sprintf(time_buff, "date -s \"%d-%d-%d %d:%d:%d\"", tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday, tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec);
system(time_buff);
#endif
return 0;
}
int main()
{
int ret;
int sock;
struct timeval newtime;
struct timeval timeout; //<sys/time.h>
int addr_len = sizeof(struct sockaddr_in);
struct sockaddr_in addr_src; //本地 socket <netinet/in.h>
struct sockaddr_in addr_dst; //服务器 socket
//UDP数据报套接字
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == -1)
{
PDEBUG("套接字创建失败,被迫终止 ! \n");
exit(1);
}
memset(&addr_src, 0, addr_len);
addr_src.sin_family = AF_INET;
addr_src.sin_port = htons(0);
addr_src.sin_addr.s_addr = htonl(INADDR_ANY); //<arpa/inet.h>
//绑定本地地址
if (-1 == bind(sock, (struct sockaddr *)&addr_src, addr_len))
{
PDEBUG("绑定失败,被迫终止 !\n");
exit(1);
}
memset(&addr_dst, 0, addr_len);
addr_dst.sin_family = AF_INET;
addr_dst.sin_port = htons(DEF_NTP_PORT);
//解析方式1
#if 0
struct hostent *host = gethostbyname(DEF_NTP_SERVER); //<netdb.h>
if (host == NULL)
{
PDEBUG("主机名获取错误,被迫终止 !\n");
exit(1);
}
memcpy(&(addr_dst.sin_addr.s_addr), host->h_addr_list[0], 4);
#endif
//解析方式2
#if 0
struct addrinfo *result;
struct addrinfo hint;
if (getaddrinfo(DEF_NTP_SERVER, NULL, &hint, &result) != 0)
{
PDEBUG("主机名获取错误,被迫终止 !\n");
exit(1);
}
struct sockaddr *sa = result->ai_addr;
bzero(&hint, sizeof(hint));
hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_STREAM;
memcpy(&(addr_dst.sin_addr.s_addr), &(((struct sockaddr_in *)sa)->sin_addr.s_addr), 4);
freeaddrinfo(result);
#endif
//解析方式3
#if 1
addr_dst.sin_addr.s_addr = inet_addr(DEF_NTP_SERVER_IP);
// memcpy(&(addr_dst.sin_addr.s_addr), &(inet_addr(DEF_NTP_SERVER_IP)), 4);
#endif
if (-1 == connect(sock, (struct sockaddr *)&addr_dst, addr_len))
{
PDEBUG("连接服务器失败,被迫终止 !\n");
exit(1);
}
send_packet(sock);
while (1)
{
fd_set fds_read;
FD_ZERO(&fds_read);
FD_SET(sock, &fds_read);
timeout.tv_sec = 30;
timeout.tv_usec = 0;
ret = select(sock + 1, &fds_read, NULL, NULL, &timeout);
if (ret == -1)
{
PDEBUG("select函数出错,被迫终止 !\n");
exit(0);
}
if (ret == 0)
{
PDEBUG("等待服务器响应超时,重发请求 !\n");
//向服务器发送数据
send_packet(sock);
continue;
}
if (FD_ISSET(sock, &fds_read))
{
if (1 == get_server_time(sock, &newtime))
{
continue;
}
mod_localtime(newtime);
sleep(20);
//发送 ntp 包
send_packet(sock);
}
}
close(sock);
return 0;
}
C
1
https://gitee.com/xie_tong/ntp_time.git
git@gitee.com:xie_tong/ntp_time.git
xie_tong
ntp_time
ntp_time
master

搜索帮助