#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "NtpClientFunc.h"
//
//rfc1305 defined from 1900 so also 2208988800 (1900 - 1970 ) seconds left
//
//timeval.tv_sec + JAN_1970 = timestamp.coarse
#define JAN_1970 0x83aa7e80
//timeval.tv_usec=>timestamp.fine
#define NTPFRAC(x) (4294 * (x) + ((1981 * (x))>>11))
//timeval.tv_usec<=timestamp.fine
#define USEC(x) (((x) >> 12) - 759 * ((((x) >> 10) + 32768) >> 16))
//创建本地UDPsocket
int CreateNtpClientSockfd()
{
int sockfd;
int addr_len;
struct sockaddr_in addr_src;
int ret;
addr_len = sizeof(struct sockaddr_in);
memset(&addr_src, 0, addr_len);
addr_src.sin_family = AF_INET;
addr_src.sin_addr.s_addr = htonl(INADDR_ANY);
addr_src.sin_port = htons(0);
/* create socket. */
if(-1==(sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)))
{
printf("create socket error!\n");
return -1;
}
/* bind local address. */
ret = bind(sockfd, (struct sockaddr*)&addr_src, addr_len);
if(-1==ret)
{
printf("bind error!\n");
close(sockfd);
return -1;
}
return sockfd;
}
//链接到NTP服务器
int ConnectNtpServer(int sockfd,char * serverAddr, int serverPort, struct sockaddr_in * ServerSocket_in)
{
int addr_len;
struct sockaddr_in addr_dst;
struct hostent* host;
int ret;
addr_len = sizeof(struct sockaddr_in);
memset(&addr_dst, 0, addr_len);
addr_dst.sin_family = AF_INET;
host = gethostbyname(serverAddr);
memcpy(&(addr_dst.sin_addr.s_addr), host->h_addr_list[0], 4);
addr_dst.sin_port = htons(serverPort);
memcpy(ServerSocket_in,&addr_dst,sizeof(struct sockaddr_in));
/* connect to ntp server. */
ret = connect(sockfd, (struct sockaddr*)&addr_dst, addr_len);
if(-1==ret)
{
printf("connect error!\n");
close(sockfd);
return -1;
}
return sockfd;
}
//发送ntp请求包,请求服务器的返回时间, sockfd为socket文件描述符,为 poll_intervals 测试间隔
void SendQueryTimePacked(int sockfd)
{
NTPPACKED SynNtpPacked;
struct timeval now;
memset(&SynNtpPacked, 0, sizeof(SynNtpPacked));
SynNtpPacked.header.local_precision = -6;
SynNtpPacked.header.Poll = 4;
SynNtpPacked.header.stratum = 0;
SynNtpPacked.header.Mode = 3;
SynNtpPacked.header.VN = 3;
SynNtpPacked.header.LI = 0;
SynNtpPacked.root_delay = 1<<16; /* Root Delay (seconds) */
SynNtpPacked.root_dispersion = 1<<16; /* Root Dispersion (seconds) */
SynNtpPacked.header.headData = htonl(SynNtpPacked.header.headData);
SynNtpPacked.root_delay = htonl(SynNtpPacked.root_dispersion);
SynNtpPacked.root_dispersion = htonl(SynNtpPacked.root_dispersion);
gettimeofday(&now, NULL); /* get current local_time*/
SynNtpPacked.trantime.coarse = htonl(now.tv_sec + JAN_1970); /* Transmit Timestamp coarse */
SynNtpPacked.trantime.fine = htonl(NTPFRAC(now.tv_usec)); /* Transmit Timestamp fine */
send(sockfd, &SynNtpPacked, sizeof(SynNtpPacked), 0);
}
//从服务器接收数据包
int RecvNtpPacked(int sockfd,PNTPPACKED pSynNtpPacked,struct sockaddr_in * ServerSocket_in)
{
int receivebytes;
int addr_len = sizeof(struct sockaddr_in);
/* recv ntp server's response. */
receivebytes = recvfrom(sockfd, pSynNtpPacked, sizeof(NTPPACKED), 0, (struct sockaddr *)ServerSocket_in, &addr_len);
if(-1==receivebytes)
{
printf("recvfrom error\n");
close(sockfd);
return -1;
}
return receivebytes;
}
//从ntp服务器返回的数据包中解析出新的时间,pSynNtpPacked为server返回给client的数据包,new_time为解析出时间
void GetSynTimeFromNtpPacked(PNTPPACKED pSynNtpPacked,struct timeval* new_time)
{
NTPTIME trantime;
trantime.coarse = ntohl(pSynNtpPacked->trantime.coarse);
trantime.fine = ntohl(pSynNtpPacked->trantime.fine);
new_time->tv_sec = trantime.coarse - JAN_1970;
new_time->tv_usec = USEC(trantime.fine);
}
//修改本地linux时间
void ModifyLocalTime(struct timeval* new_time)
{
/* need root user. */
if (0 != getuid() && 0 != geteuid())
{
printf(">>>>>not Modify localtime , you must be root user!)\n");
return;
}
settimeofday(new_time, NULL);
}
//关闭Socked句柄
void CloseSockfd(int sockfd)
{
close(sockfd);
}