⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 NTP协议的实现 可以使用该程序将linux主机的时间和网络ntp server同步时间
💻 C
字号:
#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>

#define NTP_SERVER    	"clock.via.net"
#define NTP_PORT      		123

//
//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))

#define Data(i) ntohl(((unsigned int *)data)[i])

#define LI 0
#define VN 3
#define MODE 3
#define STRATUM 0
#define POLL 4 
#define PREC -6

struct ntptime 
{
	unsigned int coarse;
	unsigned int fine;
};

void send_packet(int fd)
{
    	unsigned int data[12];
    	struct timeval now;
    	int ret;

    	if (sizeof(data) != 48) 
    	{
        	fprintf(stderr,"size error\n");
        	return;
    	}

    	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);  /* Root Delay (seconds) */
	data[2] = htonl(1<<16);  /* Root Dispersion (seconds) */
	gettimeofday(&now, NULL);
	data[10] = htonl(now.tv_sec + JAN_1970); /* Transmit Timestamp coarse */
	data[11] = htonl(NTPFRAC(now.tv_usec));  /* Transmit Timestamp fine   */
	send(fd, data, 48, 0);
}

void get_udp_arrival_local_timestamp(struct ntptime *udp_arrival_local_timestamp)
{
	struct timeval udp_arrival_local_time;
	
	gettimeofday(&udp_arrival_local_time, NULL);

	//print just precise to second
	printf("local time=>%s\n",ctime(&(udp_arrival_local_time.tv_sec)));
}

void get_new_time(unsigned int *data,struct timeval* new_time)
{
	//int li, vn, mode, stratum, poll, prec;
	//int delay, disp, refid;
	//struct ntptime reftime, orgtime, rectime;
	struct ntptime trantime;
	/*li      = Data(0) >> 30 & 0x03;
	vn      = Data(0) >> 27 & 0x07;
	mode    = Data(0) >> 24 & 0x07;
	stratum = Data(0) >> 16 & 0xff;
	poll    = Data(0) >>  8 & 0xff;
	prec    = Data(0)       & 0xff;
	if (prec & 0x80) prec|=0xffffff00;
	delay   = Data(1);
	disp    = Data(2);
	refid   = Data(3);
	reftime.coarse = Data(4);
	reftime.fine   = Data(5);
	orgtime.coarse = Data(6);
	orgtime.fine   = Data(7);
	rectime.coarse = Data(8);
	rectime.fine   = Data(9);*/
	trantime.coarse = Data(10);
	trantime.fine   = Data(11);
	
	new_time->tv_sec = trantime.coarse - JAN_1970;
	new_time->tv_usec = USEC(trantime.fine);

	//print just precise to second
	printf("server time=>%s\n",ctime(&(new_time->tv_sec)));
}

void set_local_time(struct timeval new_time)
{
	/* need root user. */
	if (0 != getuid() && 0 != geteuid())
	{
		printf("must be root user!:0)\n");
		return;
	}

	settimeofday(&new_time, NULL);
}

int main(void)
{
	int sockfd;
	struct sockaddr_in addr_src,addr_dst;
	fd_set fds_read;
	int ret;
	int receivebytes;
	unsigned int buf[12];
	int addr_len;
	
	struct timeval timeout,new_time;
	struct ntptime udp_arrival_local_timestamp;
	
	struct hostent* host; 

	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);

	memset(&addr_dst, 0, addr_len);
	addr_dst.sin_family = AF_INET;
	host = gethostbyname(NTP_SERVER);
	memcpy(&(addr_dst.sin_addr.s_addr), host->h_addr_list[0], 4);
	addr_dst.sin_port = htons(NTP_PORT);

	/* create socket. */
	if(-1==(sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)))
	{		
		printf("create socket error!\n");
		exit(1);	
	}

	/* bind local address. */
	ret = bind(sockfd, (struct sockaddr*)&addr_src, addr_len);
	if(-1==ret)	
	{		
		printf("bind error!\n");		
		close(sockfd);	
	}
	
	/* connect to ntp server. */
	ret = connect(sockfd, (struct sockaddr*)&addr_dst, addr_len);
	if(-1==ret)	
	{		
		printf("connect error!\n");		
		close(sockfd);	
	}
	/*get and set time*/
	while (1)
	{
		FD_ZERO(&fds_read);
		FD_SET(sockfd, &fds_read);

		timeout.tv_sec = 6;
		timeout.tv_usec = 0;
		ret = select(sockfd + 1, &fds_read, NULL, NULL, &timeout);
		if (0 == ret || !FD_ISSET(sockfd, &fds_read))
		{
			/* send ntp protocol packet. */
			send_packet(sockfd);
			continue;
		}
		/* recv ntp server's response. */
		receivebytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&addr_dst, &addr_len);
		if(-1==receivebytes)		
		{			
			printf("recvfrom error\n");			
			close(sockfd);			
			exit(1);		
		}
		/* get local timestamp. */
		get_udp_arrival_local_timestamp(&udp_arrival_local_timestamp);
		/* get server's time and print it. */
		get_new_time(buf, &new_time);	
		/* set local time to the server's time, if you're a root user. */
		set_local_time(new_time);
	}

	close(sockfd);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -