mirror of
https://github.com/JamesonHuang/OpenWrt_Luci_Lua.git
synced 2024-11-23 22:00:11 +00:00
ntp time polling get system time
This commit is contained in:
parent
a7aa28eb38
commit
4611b5aca5
1
1_6.h12_dev/ntp/timesync/.svn/entries
Normal file
1
1_6.h12_dev/ntp/timesync/.svn/entries
Normal file
@ -0,0 +1 @@
|
|||||||
|
12
|
1
1_6.h12_dev/ntp/timesync/.svn/format
Normal file
1
1_6.h12_dev/ntp/timesync/.svn/format
Normal file
@ -0,0 +1 @@
|
|||||||
|
12
|
Binary file not shown.
@ -0,0 +1,2 @@
|
|||||||
|
sudo ./server
|
||||||
|
./client <server ip address>
|
@ -0,0 +1,20 @@
|
|||||||
|
.PHONY: all clean tags
|
||||||
|
|
||||||
|
CFLAGS:=-Wall -O2
|
||||||
|
|
||||||
|
all: client server
|
||||||
|
|
||||||
|
server: server.c
|
||||||
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
strip -s $@
|
||||||
|
|
||||||
|
client: client.c
|
||||||
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
strip -s $@
|
||||||
|
|
||||||
|
tags:
|
||||||
|
ctags -R .
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm *.o client server
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,159 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <time.h> /* for time() and ctime() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rfc1305的ntp时间中,时间为64bit,记录1900年后的秒数(utc格式)
|
||||||
|
* 高32位是整数部分,低32位是小数部分*/
|
||||||
|
#define UTC_NTP 2208988800U /* 1970 - 1900 */
|
||||||
|
|
||||||
|
/* get Timestamp for NTP in LOCAL ENDIAN */
|
||||||
|
void gettime64(uint32_t ts[])
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
ts[0] = tv.tv_sec + UTC_NTP;
|
||||||
|
ts[1] = (4294*(tv.tv_usec)) + ((1981*(tv.tv_usec))>>11);
|
||||||
|
}
|
||||||
|
|
||||||
|
int die(const char *msg)
|
||||||
|
{
|
||||||
|
fputs(msg, stderr);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int useage(const char *path)
|
||||||
|
{
|
||||||
|
printf("Useage:\n\t%s <server address>\n", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//开始连接服务器
|
||||||
|
int open_connect(const char* server)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
struct addrinfo *saddr;
|
||||||
|
|
||||||
|
/* printf("Connecting to server: %s\n", server); */
|
||||||
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s == -1) {
|
||||||
|
die("Can not create socket.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != getaddrinfo(server, "123", NULL, &saddr)) {
|
||||||
|
die("Server address not correct.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(s, saddr->ai_addr, saddr->ai_addrlen) != 0) {
|
||||||
|
die("Connect error\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(saddr);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送请求报文
|
||||||
|
void request(int fd)
|
||||||
|
{
|
||||||
|
unsigned char buf[48] = {0};
|
||||||
|
uint32_t tts[2]; /* Transmit Timestamp */
|
||||||
|
|
||||||
|
/* LI VN MODE = 00 100 011*/
|
||||||
|
/* MODE:3表示客户模式,4表示服务器模式*/
|
||||||
|
buf[0] = 0x23;
|
||||||
|
|
||||||
|
gettime64(tts);
|
||||||
|
//此处将Originate Timestamp设置在Transmit Timestamp处
|
||||||
|
(*(uint32_t *)&buf[40]) = htonl(tts[0]);
|
||||||
|
(*(uint32_t *)&buf[44])= htonl(tts[1]);
|
||||||
|
if (send(fd, buf, 48, 0) !=48 ) {
|
||||||
|
die("Send error\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获得NTP应答报文
|
||||||
|
void get_reply(int fd)
|
||||||
|
{
|
||||||
|
unsigned char buf[48];
|
||||||
|
uint32_t *pt;
|
||||||
|
// uint32_t t_last_update[2]; /* Reference Timestamp @ Server */
|
||||||
|
uint32_t t1[2]; /* t1 = Originate Timestamp,即NTP请求报文离开发送端时发送端的本地时间 */
|
||||||
|
uint32_t t2[2]; /* t2 = Receive Timestamp @ Server,即NTP请求报文到达接收端时接收端的本地时间 */
|
||||||
|
uint32_t t3[2]; /* t3 = Transmit Timestamp @ Server,即应答报文离开应答者时应答者的本地时间 */
|
||||||
|
uint32_t t4[2]; /* t4 = Receive Timestamp @ Client */
|
||||||
|
double T1, T2, T3, T4;
|
||||||
|
double tfrac = 4294967296.0;
|
||||||
|
time_t curr_time;
|
||||||
|
time_t diff_sec;
|
||||||
|
|
||||||
|
if (recv(fd, buf, 48, 0) < 48) {
|
||||||
|
die("Receive error\n");
|
||||||
|
}
|
||||||
|
gettime64(t4);
|
||||||
|
pt = (uint32_t *)&buf[24];
|
||||||
|
|
||||||
|
t1[0] = htonl(*pt++);
|
||||||
|
t1[1] = htonl(*pt++);
|
||||||
|
|
||||||
|
t2[0] = htonl(*pt++);
|
||||||
|
t2[1] = htonl(*pt++);
|
||||||
|
|
||||||
|
t3[0] = htonl(*pt++);
|
||||||
|
t3[1] = htonl(*pt++);
|
||||||
|
|
||||||
|
/* t1 = Transmit Timestamp @ Client */
|
||||||
|
/*
|
||||||
|
* (Version=4, Mode=Server,
|
||||||
|
* Stratum = 0-15, etc.)*/
|
||||||
|
|
||||||
|
T1 = t1[0] + t1[1]/tfrac;
|
||||||
|
T2 = t2[0] + t2[1]/tfrac;
|
||||||
|
T3 = t3[0] + t3[1]/tfrac;
|
||||||
|
T4 = t4[0] + t4[1]/tfrac;
|
||||||
|
|
||||||
|
//delay:NTP报文的往返时延
|
||||||
|
//offset:client与server的时间差
|
||||||
|
printf( "\ndelay = %lf\n"
|
||||||
|
"offset = %lf\n\n",
|
||||||
|
(T4-T1) - (T3-T2),
|
||||||
|
((T2 - T1) + (T3 - T4)) /2
|
||||||
|
);
|
||||||
|
|
||||||
|
diff_sec = ((int32_t)(t2[0] - t1[0]) + (int32_t)(t3[0] - t4[0])) /2;
|
||||||
|
curr_time = time(NULL) - diff_sec;
|
||||||
|
printf("Current Time at Server: %s\n", ctime(&curr_time));
|
||||||
|
}
|
||||||
|
|
||||||
|
int client(const char* server)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open_connect(server);
|
||||||
|
request(fd);
|
||||||
|
get_reply(fd);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char **env)
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
return useage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return client(argv[1]);
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <time.h> /* for time() and ctime() */
|
||||||
|
|
||||||
|
//1900至1970年间经过的总秒数
|
||||||
|
#define UTC_NTP 2208988800U /* 1970 - 1900 */
|
||||||
|
|
||||||
|
/* get Timestamp for NTP in LOCAL ENDIAN */
|
||||||
|
void gettime64(uint32_t ts[])
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
ts[0] = tv.tv_sec + UTC_NTP;
|
||||||
|
ts[1] = (4294*(tv.tv_usec)) + ((1981*(tv.tv_usec))>>11);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int die(const char *msg)
|
||||||
|
{
|
||||||
|
if (msg) {
|
||||||
|
fputs(msg, stderr);
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void log_request_arrive(uint32_t *ntp_time)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if (ntp_time) {
|
||||||
|
t = *ntp_time - UTC_NTP;
|
||||||
|
} else {
|
||||||
|
t = time(NULL);
|
||||||
|
}
|
||||||
|
printf("A request comes at: %s", ctime(&t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void log_ntp_event(char *msg)
|
||||||
|
{
|
||||||
|
puts(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//应答client
|
||||||
|
int ntp_reply(
|
||||||
|
int socket_fd,
|
||||||
|
struct sockaddr *saddr_p,
|
||||||
|
socklen_t saddrlen,
|
||||||
|
unsigned char recv_buf[],
|
||||||
|
uint32_t recv_time[])
|
||||||
|
{
|
||||||
|
/* Assume that recv_time is in local endian ! */
|
||||||
|
unsigned char send_buf[48];
|
||||||
|
uint32_t *u32p;
|
||||||
|
|
||||||
|
/* do not use 0xC7 because the LI=11 can be `unsynchronized` */
|
||||||
|
if ((recv_buf[0] & 0x07/*0xC7*/) != 0x3) {
|
||||||
|
/* LI VN Mode stimmt nicht */
|
||||||
|
log_ntp_event("Invalid request: found error at the first byte");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 设置 LI VN Mode 的值
|
||||||
|
LI = 0
|
||||||
|
VN = Version Number 同 Client
|
||||||
|
Mode = 4
|
||||||
|
*/
|
||||||
|
send_buf[0] = (recv_buf[0] & 0x38) + 4;
|
||||||
|
|
||||||
|
/* Stratum */
|
||||||
|
send_buf[1] = 0x01;
|
||||||
|
/* Reference ID = "LOCL" ,即参考时钟源的标识*/
|
||||||
|
*(uint32_t*)&send_buf[12] = htonl(0x4C4F434C);
|
||||||
|
|
||||||
|
/* Copy Poll */
|
||||||
|
send_buf[2] = recv_buf[2];
|
||||||
|
|
||||||
|
/* Precision in Microsecond ( from API gettimeofday() ) */
|
||||||
|
send_buf[3] = (signed char)(-6); /* 2^(-6) sec */
|
||||||
|
|
||||||
|
u32p = (uint32_t *)&send_buf[4];
|
||||||
|
/* 设置Root Delay = 0, Root Dispersion = 0 */
|
||||||
|
*u32p++ = 0;
|
||||||
|
*u32p++ = 0;
|
||||||
|
|
||||||
|
/* Reference ID前面已经设置*/
|
||||||
|
u32p++;
|
||||||
|
|
||||||
|
/* 设置 Reference TimeStamp */
|
||||||
|
gettime64(u32p);
|
||||||
|
*u32p = htonl(*u32p - 60); /* -1 Min.*/
|
||||||
|
u32p++;
|
||||||
|
*u32p = htonl(*u32p); /* -1 Min.*/
|
||||||
|
u32p++;
|
||||||
|
|
||||||
|
/* Originate Time = Transmit Time @ Client */
|
||||||
|
*u32p++ = *(uint32_t *)&recv_buf[40];
|
||||||
|
*u32p++ = *(uint32_t *)&recv_buf[44];
|
||||||
|
|
||||||
|
/* Receive Time @ Server */
|
||||||
|
*u32p++ = htonl(recv_time[0]);
|
||||||
|
*u32p++ = htonl(recv_time[1]);
|
||||||
|
|
||||||
|
/* 设置 Transmit Time*/
|
||||||
|
gettime64(u32p);
|
||||||
|
*u32p = htonl(*u32p); /* -1 Min.*/
|
||||||
|
u32p++;
|
||||||
|
*u32p = htonl(*u32p); /* -1 Min.*/
|
||||||
|
|
||||||
|
if ( sendto( socket_fd,
|
||||||
|
send_buf,
|
||||||
|
sizeof(send_buf), 0,
|
||||||
|
saddr_p, saddrlen)
|
||||||
|
< 48) {
|
||||||
|
perror("sendto error");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void request_process_loop(int fd)
|
||||||
|
{
|
||||||
|
struct sockaddr src_addr;
|
||||||
|
socklen_t src_addrlen = sizeof(src_addr);
|
||||||
|
unsigned char buf[48];
|
||||||
|
uint32_t recv_time[2];
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
while (recvfrom(fd, buf,
|
||||||
|
48, 0,
|
||||||
|
&src_addr,
|
||||||
|
&src_addrlen)
|
||||||
|
< 48 ); /* invalid request */
|
||||||
|
|
||||||
|
gettime64(recv_time);
|
||||||
|
/* recv_time in local endian */
|
||||||
|
log_request_arrive(recv_time);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
/* Child */
|
||||||
|
ntp_reply(fd, &src_addr , src_addrlen, buf, recv_time);
|
||||||
|
exit(0);
|
||||||
|
} else if (pid == -1) {
|
||||||
|
perror("fork() error");
|
||||||
|
die(NULL);
|
||||||
|
}
|
||||||
|
/* return to parent */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ntp_server()
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
struct sockaddr_in sinaddr;
|
||||||
|
|
||||||
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s == -1) {
|
||||||
|
perror("Can not create socket.");
|
||||||
|
die(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sinaddr, 0, sizeof(sinaddr));
|
||||||
|
sinaddr.sin_family = AF_INET;
|
||||||
|
//NTP基于UDP报文传输,使用的UDP端口号为123
|
||||||
|
sinaddr.sin_port = htons(123);
|
||||||
|
sinaddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
if (0 != bind(s, (struct sockaddr *)&sinaddr, sizeof(sinaddr))) {
|
||||||
|
perror("Bind error");
|
||||||
|
die(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_ntp_event( "\n========================================\n"
|
||||||
|
"= Server started, waiting for requests =\n"
|
||||||
|
"========================================\n");
|
||||||
|
|
||||||
|
request_process_loop(s);
|
||||||
|
close(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wait_wrapper()
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
wait(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char **env)
|
||||||
|
{
|
||||||
|
signal(SIGCHLD,wait_wrapper);
|
||||||
|
ntp_server();
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
1_6.h12_dev/ntp/timesync/.svn/wc.db
Normal file
BIN
1_6.h12_dev/ntp/timesync/.svn/wc.db
Normal file
Binary file not shown.
20
1_6.h12_dev/ntp/timesync/Makefile
Normal file
20
1_6.h12_dev/ntp/timesync/Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.PHONY: all clean tags
|
||||||
|
|
||||||
|
CFLAGS:=-Wall -O2
|
||||||
|
|
||||||
|
all: client server
|
||||||
|
|
||||||
|
server: server.c
|
||||||
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
strip -s $@
|
||||||
|
|
||||||
|
client: client.c
|
||||||
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
strip -s $@
|
||||||
|
|
||||||
|
tags:
|
||||||
|
ctags -R .
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm *.o client server
|
||||||
|
|
2
1_6.h12_dev/ntp/timesync/README
Normal file
2
1_6.h12_dev/ntp/timesync/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
sudo ./server
|
||||||
|
./client <server ip address>
|
BIN
1_6.h12_dev/ntp/timesync/client
Executable file
BIN
1_6.h12_dev/ntp/timesync/client
Executable file
Binary file not shown.
165
1_6.h12_dev/ntp/timesync/client.c
Normal file
165
1_6.h12_dev/ntp/timesync/client.c
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <time.h> /* for time() and ctime() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rfc1305的ntp时间中,时间为64bit,记录1900年后的秒数(utc格式)
|
||||||
|
* 高32位是整数部分,低32位是小数部分*/
|
||||||
|
#define UTC_NTP 2208988800U /* 1970 - 1900 */
|
||||||
|
|
||||||
|
/* get Timestamp for NTP in LOCAL ENDIAN */
|
||||||
|
void gettime64(uint32_t ts[])
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
ts[0] = tv.tv_sec + UTC_NTP;
|
||||||
|
ts[1] = (4294*(tv.tv_usec)) + ((1981*(tv.tv_usec))>>11);
|
||||||
|
}
|
||||||
|
|
||||||
|
int die(const char *msg)
|
||||||
|
{
|
||||||
|
fputs(msg, stderr);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int useage(const char *path)
|
||||||
|
{
|
||||||
|
printf("Useage:\n\t%s <server address>\n", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//开始连接服务器
|
||||||
|
int open_connect(const char* server)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
struct addrinfo *saddr;
|
||||||
|
|
||||||
|
/* printf("Connecting to server: %s\n", server); */
|
||||||
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s == -1) {
|
||||||
|
die("Can not create socket.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != getaddrinfo(server, "123", NULL, &saddr)) {
|
||||||
|
die("Server address not correct.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(s, saddr->ai_addr, saddr->ai_addrlen) != 0) {
|
||||||
|
die("Connect error\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(saddr);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送请求报文
|
||||||
|
void request(int fd)
|
||||||
|
{
|
||||||
|
unsigned char buf[48] = {0};
|
||||||
|
uint32_t tts[2]; /* Transmit Timestamp */
|
||||||
|
|
||||||
|
/* LI VN MODE = 00 100 011*/
|
||||||
|
/* MODE:3表示客户模式,4表示服务器模式*/
|
||||||
|
buf[0] = 0x23;
|
||||||
|
|
||||||
|
gettime64(tts);
|
||||||
|
//此处将Originate Timestamp设置在Transmit Timestamp处
|
||||||
|
(*(uint32_t *)&buf[40]) = htonl(tts[0]);
|
||||||
|
(*(uint32_t *)&buf[44])= htonl(tts[1]);
|
||||||
|
if (send(fd, buf, 48, 0) !=48 ) {
|
||||||
|
die("Send error\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获得NTP应答报文
|
||||||
|
void get_reply(int fd)
|
||||||
|
{
|
||||||
|
unsigned char buf[48];
|
||||||
|
uint32_t *pt;
|
||||||
|
// uint32_t t_last_update[2]; /* Reference Timestamp @ Server */
|
||||||
|
uint32_t t1[2]; /* t1 = Originate Timestamp,即NTP请求报文离开发送端时发送端的本地时间 */
|
||||||
|
uint32_t t2[2]; /* t2 = Receive Timestamp @ Server,即NTP请求报文到达接收端时接收端的本地时间 */
|
||||||
|
uint32_t t3[2]; /* t3 = Transmit Timestamp @ Server,即应答报文离开应答者时应答者的本地时间 */
|
||||||
|
uint32_t t4[2]; /* t4 = Receive Timestamp @ Client */
|
||||||
|
double T1, T2, T3, T4;
|
||||||
|
double tfrac = 4294967296.0;
|
||||||
|
time_t curr_time;
|
||||||
|
time_t diff_sec;
|
||||||
|
|
||||||
|
if (recv(fd, buf, 48, 0) < 48) {
|
||||||
|
die("Receive error\n");
|
||||||
|
}
|
||||||
|
gettime64(t4);
|
||||||
|
pt = (uint32_t *)&buf[24];
|
||||||
|
|
||||||
|
t1[0] = htonl(*pt++);
|
||||||
|
t1[1] = htonl(*pt++);
|
||||||
|
|
||||||
|
t2[0] = htonl(*pt++);
|
||||||
|
t2[1] = htonl(*pt++);
|
||||||
|
|
||||||
|
t3[0] = htonl(*pt++);
|
||||||
|
t3[1] = htonl(*pt++);
|
||||||
|
|
||||||
|
/* t1 = Transmit Timestamp @ Client */
|
||||||
|
/*
|
||||||
|
* (Version=4, Mode=Server,
|
||||||
|
* Stratum = 0-15, etc.)*/
|
||||||
|
|
||||||
|
T1 = t1[0] + t1[1]/tfrac;
|
||||||
|
T2 = t2[0] + t2[1]/tfrac;
|
||||||
|
T3 = t3[0] + t3[1]/tfrac;
|
||||||
|
T4 = t4[0] + t4[1]/tfrac;
|
||||||
|
|
||||||
|
//delay:NTP报文的往返时延
|
||||||
|
//offset:client与server的时间差
|
||||||
|
printf( "\ndelay = %lf\n"
|
||||||
|
"offset = %lf\n\n",
|
||||||
|
(T4-T1) - (T3-T2),
|
||||||
|
((T2 - T1) + (T3 - T4)) /2
|
||||||
|
);
|
||||||
|
|
||||||
|
diff_sec = ((int32_t)(t2[0] - t1[0]) + (int32_t)(t3[0] - t4[0])) /2;
|
||||||
|
curr_time = time(NULL) - diff_sec;
|
||||||
|
printf("Current Time at Server: %s\n", ctime(&curr_time));
|
||||||
|
printf("Current TimeStamp at Server: %d\n", (int)curr_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
int client(const char* server)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open_connect(server);
|
||||||
|
request(fd);
|
||||||
|
get_reply(fd);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char **env)
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
return useage(argv[0]);
|
||||||
|
}
|
||||||
|
//return client(argv[1]);
|
||||||
|
client(argv[1]);
|
||||||
|
sleep(3);
|
||||||
|
}
|
||||||
|
}
|
BIN
1_6.h12_dev/ntp/timesync/server
Executable file
BIN
1_6.h12_dev/ntp/timesync/server
Executable file
Binary file not shown.
213
1_6.h12_dev/ntp/timesync/server.c
Normal file
213
1_6.h12_dev/ntp/timesync/server.c
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <time.h> /* for time() and ctime() */
|
||||||
|
|
||||||
|
//1900至1970年间经过的总秒数
|
||||||
|
#define UTC_NTP 2208988800U /* 1970 - 1900 */
|
||||||
|
|
||||||
|
/* get Timestamp for NTP in LOCAL ENDIAN */
|
||||||
|
void gettime64(uint32_t ts[])
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
ts[0] = tv.tv_sec + UTC_NTP;
|
||||||
|
ts[1] = (4294*(tv.tv_usec)) + ((1981*(tv.tv_usec))>>11);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int die(const char *msg)
|
||||||
|
{
|
||||||
|
if (msg) {
|
||||||
|
fputs(msg, stderr);
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void log_request_arrive(uint32_t *ntp_time)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if (ntp_time) {
|
||||||
|
t = *ntp_time - UTC_NTP;
|
||||||
|
} else {
|
||||||
|
t = time(NULL);
|
||||||
|
}
|
||||||
|
printf("A request comes at: %s", ctime(&t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void log_ntp_event(char *msg)
|
||||||
|
{
|
||||||
|
puts(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//应答client
|
||||||
|
int ntp_reply(
|
||||||
|
int socket_fd,
|
||||||
|
struct sockaddr *saddr_p,
|
||||||
|
socklen_t saddrlen,
|
||||||
|
unsigned char recv_buf[],
|
||||||
|
uint32_t recv_time[])
|
||||||
|
{
|
||||||
|
/* Assume that recv_time is in local endian ! */
|
||||||
|
unsigned char send_buf[48];
|
||||||
|
uint32_t *u32p;
|
||||||
|
|
||||||
|
/* do not use 0xC7 because the LI=11 can be `unsynchronized` */
|
||||||
|
if ((recv_buf[0] & 0x07/*0xC7*/) != 0x3) {
|
||||||
|
/* LI VN Mode stimmt nicht */
|
||||||
|
log_ntp_event("Invalid request: found error at the first byte");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 设置 LI VN Mode 的值
|
||||||
|
LI = 0
|
||||||
|
VN = Version Number 同 Client
|
||||||
|
Mode = 4
|
||||||
|
*/
|
||||||
|
send_buf[0] = (recv_buf[0] & 0x38) + 4;
|
||||||
|
|
||||||
|
/* Stratum */
|
||||||
|
send_buf[1] = 0x01;
|
||||||
|
/* Reference ID = "LOCL" ,即参考时钟源的标识*/
|
||||||
|
*(uint32_t*)&send_buf[12] = htonl(0x4C4F434C);
|
||||||
|
|
||||||
|
/* Copy Poll */
|
||||||
|
send_buf[2] = recv_buf[2];
|
||||||
|
|
||||||
|
/* Precision in Microsecond ( from API gettimeofday() ) */
|
||||||
|
send_buf[3] = (signed char)(-6); /* 2^(-6) sec */
|
||||||
|
|
||||||
|
u32p = (uint32_t *)&send_buf[4];
|
||||||
|
/* 设置Root Delay = 0, Root Dispersion = 0 */
|
||||||
|
*u32p++ = 0;
|
||||||
|
*u32p++ = 0;
|
||||||
|
|
||||||
|
/* Reference ID前面已经设置*/
|
||||||
|
u32p++;
|
||||||
|
|
||||||
|
/* 设置 Reference TimeStamp */
|
||||||
|
gettime64(u32p);
|
||||||
|
*u32p = htonl(*u32p - 60); /* -1 Min.*/
|
||||||
|
u32p++;
|
||||||
|
*u32p = htonl(*u32p); /* -1 Min.*/
|
||||||
|
u32p++;
|
||||||
|
|
||||||
|
/* Originate Time = Transmit Time @ Client */
|
||||||
|
*u32p++ = *(uint32_t *)&recv_buf[40];
|
||||||
|
*u32p++ = *(uint32_t *)&recv_buf[44];
|
||||||
|
|
||||||
|
/* Receive Time @ Server */
|
||||||
|
*u32p++ = htonl(recv_time[0]);
|
||||||
|
*u32p++ = htonl(recv_time[1]);
|
||||||
|
|
||||||
|
/* 设置 Transmit Time*/
|
||||||
|
gettime64(u32p);
|
||||||
|
*u32p = htonl(*u32p); /* -1 Min.*/
|
||||||
|
u32p++;
|
||||||
|
*u32p = htonl(*u32p); /* -1 Min.*/
|
||||||
|
|
||||||
|
if ( sendto( socket_fd,
|
||||||
|
send_buf,
|
||||||
|
sizeof(send_buf), 0,
|
||||||
|
saddr_p, saddrlen)
|
||||||
|
< 48) {
|
||||||
|
perror("sendto error");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void request_process_loop(int fd)
|
||||||
|
{
|
||||||
|
struct sockaddr src_addr;
|
||||||
|
socklen_t src_addrlen = sizeof(src_addr);
|
||||||
|
unsigned char buf[48];
|
||||||
|
uint32_t recv_time[2];
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
while (recvfrom(fd, buf,
|
||||||
|
48, 0,
|
||||||
|
&src_addr,
|
||||||
|
&src_addrlen)
|
||||||
|
< 48 ); /* invalid request */
|
||||||
|
|
||||||
|
gettime64(recv_time);
|
||||||
|
/* recv_time in local endian */
|
||||||
|
log_request_arrive(recv_time);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
/* Child */
|
||||||
|
ntp_reply(fd, &src_addr , src_addrlen, buf, recv_time);
|
||||||
|
exit(0);
|
||||||
|
} else if (pid == -1) {
|
||||||
|
perror("fork() error");
|
||||||
|
die(NULL);
|
||||||
|
}
|
||||||
|
/* return to parent */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ntp_server()
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
struct sockaddr_in sinaddr;
|
||||||
|
|
||||||
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s == -1) {
|
||||||
|
perror("Can not create socket.");
|
||||||
|
die(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sinaddr, 0, sizeof(sinaddr));
|
||||||
|
sinaddr.sin_family = AF_INET;
|
||||||
|
//NTP基于UDP报文传输,使用的UDP端口号为123
|
||||||
|
sinaddr.sin_port = htons(123);
|
||||||
|
sinaddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
if (0 != bind(s, (struct sockaddr *)&sinaddr, sizeof(sinaddr))) {
|
||||||
|
perror("Bind error");
|
||||||
|
die(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_ntp_event( "\n========================================\n"
|
||||||
|
"= Server started, waiting for requests =\n"
|
||||||
|
"========================================\n");
|
||||||
|
|
||||||
|
request_process_loop(s);
|
||||||
|
close(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wait_wrapper()
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
wait(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char **env)
|
||||||
|
{
|
||||||
|
signal(SIGCHLD,wait_wrapper);
|
||||||
|
ntp_server();
|
||||||
|
return 0;
|
||||||
|
}
|
26
1_6.h12_dev/ntp/timesync/tags
Normal file
26
1_6.h12_dev/ntp/timesync/tags
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||||
|
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||||
|
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
||||||
|
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
||||||
|
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
||||||
|
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
|
||||||
|
CFLAGS Makefile /^CFLAGS:=-Wall -O2$/;" m
|
||||||
|
UTC_NTP client.c 17;" d file:
|
||||||
|
UTC_NTP server.c 18;" d file:
|
||||||
|
client client.c /^int client(const char* server)$/;" f
|
||||||
|
die client.c /^int die(const char *msg)$/;" f
|
||||||
|
die server.c /^int die(const char *msg)$/;" f
|
||||||
|
get_reply client.c /^void get_reply(int fd)$/;" f
|
||||||
|
gettime64 client.c /^void gettime64(uint32_t ts[])$/;" f
|
||||||
|
gettime64 server.c /^void gettime64(uint32_t ts[])$/;" f
|
||||||
|
log_ntp_event server.c /^void log_ntp_event(char *msg)$/;" f
|
||||||
|
log_request_arrive server.c /^void log_request_arrive(uint32_t *ntp_time)$/;" f
|
||||||
|
main client.c /^int main(int argc, char *argv[], char **env)$/;" f
|
||||||
|
main server.c /^int main(int argc, char *argv[], char **env)$/;" f
|
||||||
|
ntp_reply server.c /^int ntp_reply($/;" f
|
||||||
|
ntp_server server.c /^void ntp_server()$/;" f
|
||||||
|
open_connect client.c /^int open_connect(const char* server)$/;" f
|
||||||
|
request client.c /^void request(int fd)$/;" f
|
||||||
|
request_process_loop server.c /^void request_process_loop(int fd)$/;" f
|
||||||
|
useage client.c /^int useage(const char *path)$/;" f
|
||||||
|
wait_wrapper server.c /^void wait_wrapper()$/;" f
|
Loading…
Reference in New Issue
Block a user