ntp time polling get system time

This commit is contained in:
JamesonHuang 2015-07-08 19:16:28 +08:00
parent a7aa28eb38
commit 4611b5aca5
16 changed files with 822 additions and 0 deletions

View File

@ -0,0 +1 @@
12

View File

@ -0,0 +1 @@
12

View File

@ -0,0 +1,2 @@
sudo ./server
./client <server ip address>

View 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

View File

@ -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*/
/* MODE3表示客户模式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;
//delayNTP报文的往返时延
//offsetclient与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]);
}

View 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;
}

Binary file not shown.

View 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

View File

@ -0,0 +1,2 @@
sudo ./server
./client <server ip address>

BIN
1_6.h12_dev/ntp/timesync/client Executable file

Binary file not shown.

View 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时间中64bit1900utc格式
* 3232*/
#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*/
/* MODE3表示客户模式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;
//delayNTP报文的往返时延
//offsetclient与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

Binary file not shown.

View 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;
}

View 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