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

📄 ntpclient.c

📁 实现linux系统和网络时钟服务器的时间同步,从而可以得到准确的时间.
💻 C
📖 第 1 页 / 共 2 页
字号:
		li, vn, mode, stratum, poll, prec);	printf("Delay=%.1f  Dispersion=%.1f  Refid=%u.%u.%u.%u\n",		sec2u(delay),sec2u(disp),		refid>>24&0xff, refid>>16&0xff, refid>>8&0xff, refid&0xff);	printf("Reference %u.%.6u\n", reftime.coarse, USEC(reftime.fine));	printf("(sent)    %u.%.6u\n", ntpc->time_of_send[0], USEC(ntpc->time_of_send[1]));	printf("Originate %u.%.6u\n", orgtime.coarse, USEC(orgtime.fine));	printf("Receive   %u.%.6u\n", rectime.coarse, USEC(rectime.fine));	printf("Transmit  %u.%.6u\n", xmttime.coarse, USEC(xmttime.fine));	printf("Our recv  %u.%.6u\n", arrival->coarse, USEC(arrival->fine));	}	el_time=ntpdiff(&orgtime,arrival);   /* elapsed */	st_time=ntpdiff(&rectime,&xmttime);  /* stall */	skew1=ntpdiff(&orgtime,&rectime);	skew2=ntpdiff(&xmttime,arrival);	freq=get_current_freq();	if (debug) {	printf("Total elapsed: %9.2f\n"	       "Server stall:  %9.2f\n"	       "Slop:          %9.2f\n",		el_time, st_time, el_time-st_time);	printf("Skew:          %9.2f\n"	       "Frequency:     %9d\n"	       " day   second     elapsed    stall     skew  dispersion  freq\n",		(skew1-skew2)/2, freq);	}	/* error checking, see RFC-4330 section 5 */#ifdef ENABLE_DEBUG#define FAIL(x) do { drop_reason=(x); goto fail;} while (0)#else#define FAIL(x) goto fail;#endif	if (ntpc->cross_check) {		if (li == 3) FAIL("LI==3");  /* unsynchronized */		if (vn < 3) FAIL("VN<3");   /* RFC-4330 documents SNTP v4, but we interoperate with NTP v3 */		if (mode != 4) FAIL("MODE!=3");		if (orgtime.coarse != ntpc->time_of_send[0] ||		    orgtime.fine   != ntpc->time_of_send[1] ) FAIL("ORG!=sent");		if (xmttime.coarse == 0 && xmttime.fine == 0) FAIL("XMT==0");		if (delay > 65536 || delay < -65536) FAIL("abs(DELAY)>65536");		if (disp  > 65536 || disp  < -65536) FAIL("abs(DISP)>65536");		if (stratum == 0) FAIL("STRATUM==0");  /* kiss o' death */#undef FAIL	}	/* XXX should I do this if debug flag is set? */	if (ntpc->set_clock) { /* you'd better be root, or ntpclient will crash! */		set_time(&xmttime);	}	/* Not the ideal order for printing, but we want to be sure	 * to do all the time-sensitive thinking (and time setting)	 * before we start the output, especially fflush() (which	 * could be slow).  Of course, if debug is turned on, speed	 * has gone down the drain anyway. */	if (ntpc->live) {		int new_freq;		new_freq = contemplate_data(arrival->coarse, (skew1-skew2)/2,			el_time+sec2u(disp), freq);		if (!debug && new_freq != freq) set_freq(new_freq);	}	printf("%d %.5d.%.3d  %8.1f %8.1f  %8.1f %8.1f %9d\n",		arrival->coarse/86400, arrival->coarse%86400,		arrival->fine/4294967, el_time, st_time,		(skew1-skew2)/2, sec2u(disp), freq);	fflush(stdout);	*error = el_time-st_time;	return 0;fail:#ifdef ENABLE_DEBUG	printf("%d %.5d.%.3d  rejected packet: %s\n",		arrival->coarse/86400, arrival->coarse%86400,		arrival->fine/4294967, drop_reason);#else	printf("%d %.5d.%.3d  rejected packet\n",		arrival->coarse/86400, arrival->coarse%86400,		arrival->fine/4294967);#endif	return 1;}static void stuff_net_addr(struct in_addr *p, char *hostname){	struct hostent *ntpserver;	ntpserver=gethostbyname(hostname);	if (ntpserver == NULL) {		herror(hostname);		exit(1);	}	if (ntpserver->h_length != 4) {		/* IPv4 only, until I get a chance to test IPv6 */		fprintf(stderr,"oops %d\n",ntpserver->h_length);		exit(1);	}	memcpy(&(p->s_addr),ntpserver->h_addr_list[0],4);}static void setup_receive(int usd, unsigned int interface, short port){	struct sockaddr_in sa_rcvr;	memset(&sa_rcvr,0,sizeof sa_rcvr);	sa_rcvr.sin_family=AF_INET;	sa_rcvr.sin_addr.s_addr=htonl(interface);	sa_rcvr.sin_port=htons(port);	if(bind(usd,(struct sockaddr *) &sa_rcvr,sizeof sa_rcvr) == -1) {		perror("bind");		fprintf(stderr,"could not bind to udp port %d\n",port);		exit(1);	}	/* listen(usd,3); this isn't TCP; thanks Alexander! */}static void setup_transmit(int usd, char *host, short port, struct ntp_control *ntpc){	struct sockaddr_in sa_dest;	memset(&sa_dest,0,sizeof sa_dest);	sa_dest.sin_family=AF_INET;	stuff_net_addr(&(sa_dest.sin_addr),host);	memcpy(ntpc->serv_addr,&(sa_dest.sin_addr),4); /* XXX asumes IPv4 */	sa_dest.sin_port=htons(port);	if (connect(usd,(struct sockaddr *)&sa_dest,sizeof sa_dest)==-1)		{perror("connect");exit(1);}}static void primary_loop(int usd, struct ntp_control *ntpc){	fd_set fds;	struct sockaddr sa_xmit;	int i, pack_len, probes_sent, error;	unsigned int sa_xmit_len;	struct timeval to;	struct ntptime udp_arrival_ntp;	static u32 incoming_word[325];#define incoming ((char *) incoming_word)#define sizeof_incoming (sizeof incoming_word)	if (debug) printf("Listening...\n");	probes_sent=0;	sa_xmit_len=sizeof sa_xmit;	to.tv_sec=0;	to.tv_usec=0;	for (;;) {		FD_ZERO(&fds);		FD_SET(usd,&fds);		i=select(usd+1,&fds,NULL,NULL,&to);  /* Wait on read or error */		if ((i!=1)||(!FD_ISSET(usd,&fds))) {			if (i<0) {				if (errno != EINTR) perror("select");				continue;			}			if (to.tv_sec == 0) {				if (probes_sent >= ntpc->probe_count &&					ntpc->probe_count != 0) break;				send_packet(usd,ntpc->time_of_send);				++probes_sent;				to.tv_sec=ntpc->cycle_time;				to.tv_usec=0;			}			continue;		}		pack_len=recvfrom(usd,incoming,sizeof_incoming,0,		                  &sa_xmit,&sa_xmit_len);		error = ntpc->goodness;		if (pack_len<0) {			perror("recvfrom");		} else if (pack_len>0 && (unsigned)pack_len<sizeof_incoming){			get_packet_timestamp(usd, &udp_arrival_ntp);			if (check_source(pack_len, &sa_xmit, sa_xmit_len, ntpc)!=0) continue;			if (rfc1305print(incoming_word, &udp_arrival_ntp, ntpc, &error)!=0) continue;			/* udp_handle(usd,incoming,pack_len,&sa_xmit,sa_xmit_len); */		} else {			printf("Ooops.  pack_len=%d\n",pack_len);			fflush(stdout);		}		/* best rollover option: specify -g, -s, and -l.		 * simpler rollover option: specify -s and -l, which		 * triggers a magic -c 1 */		if (( error < ntpc->goodness && ntpc->goodness != 0 ) ||		    (probes_sent >= ntpc->probe_count && ntpc->probe_count != 0)) {			ntpc->set_clock = 0;			if (!ntpc->live) break;		}	}#undef incoming#undef sizeof_incoming}#ifdef ENABLE_REPLAYstatic void do_replay(void){	char line[100];	int n, day, freq, absolute;	float sec, el_time, st_time, disp;	double skew, errorbar;	int simulated_freq = 0;	unsigned int last_fake_time = 0;	double fake_delta_time = 0.0;	while (fgets(line,sizeof line,stdin)) {		n=sscanf(line,"%d %f %f %f %lf %f %d",			&day, &sec, &el_time, &st_time, &skew, &disp, &freq);		if (n==7) {			fputs(line,stdout);			absolute=day*86400+(int)sec;			errorbar=el_time+disp;			if (debug) printf("contemplate %u %.1f %.1f %d\n",				absolute,skew,errorbar,freq);			if (last_fake_time==0) simulated_freq=freq;			fake_delta_time += (absolute-last_fake_time)*((double)(freq-simulated_freq))/65536;			if (debug) printf("fake %f %d \n", fake_delta_time, simulated_freq);			skew += fake_delta_time;			freq = simulated_freq;			last_fake_time=absolute;			simulated_freq = contemplate_data(absolute, skew, errorbar, freq);		} else {			fprintf(stderr,"Replay input error\n");			exit(2);		}	}}#endifstatic void usage(char *argv0){	fprintf(stderr,	"Usage: %s [-c count]"#ifdef ENABLE_DEBUG	" [-d]"#endif	" [-f frequency] [-g goodness] -h hostname\n"	"\t[-i interval] [-l] [-p port] [-q min_delay]"#ifdef ENABLE_REPLAY	" [-r]"#endif	" [-s] [-t]\n",	argv0);}int main(int argc, char *argv[]) {	int usd;  /* socket */	int c;	/* These parameters are settable from the command line	   the initializations here provide default behavior */	short int udp_local_port=0;   /* default of 0 means kernel chooses */	char *hostname=NULL;          /* must be set */	int initial_freq;             /* initial freq value to use */	struct ntp_control ntpc;	ntpc.live=0;	ntpc.set_clock=0;	ntpc.probe_count=0;           /* default of 0 means loop forever */	ntpc.cycle_time=600;          /* seconds */	ntpc.goodness=0;	ntpc.cross_check=1;	for (;;) {		c = getopt( argc, argv, "c:" DEBUG_OPTION "f:g:h:i:lp:q:" REPLAY_OPTION "st");		if (c == EOF) break;		switch (c) {			case 'c':				ntpc.probe_count = atoi(optarg);				break;#ifdef ENABLE_DEBUG			case 'd':				++debug;				break;#endif			case 'f':				initial_freq = atoi(optarg);				if (debug) printf("initial frequency %d\n",						initial_freq);				set_freq(initial_freq);				break;			case 'g':				ntpc.goodness = atoi(optarg);				break;			case 'h':				hostname = optarg;				break;			case 'i':				ntpc.cycle_time = atoi(optarg);				break;			case 'l':				(ntpc.live)++;				break;			case 'p':				udp_local_port = atoi(optarg);				break;			case 'q':				min_delay = atof(optarg);				break;#ifdef ENABLE_REPLAY			case 'r':				do_replay();				exit(0);				break;#endif			case 's':				(ntpc.set_clock)++;				break;			case 't':				(ntpc.cross_check)=0;				break;			default:				usage(argv[0]);				exit(1);		}	}	if (hostname == NULL) {		usage(argv[0]);		exit(1);	}	if (ntpc.set_clock && !ntpc.live && !ntpc.goodness && !ntpc.probe_count) {		ntpc.probe_count = 1;	}	/* respect only applicable MUST of RFC-4330 */	if (ntpc.probe_count != 1 && ntpc.cycle_time < MIN_INTERVAL) {		ntpc.cycle_time=MIN_INTERVAL;	}	if (debug) {		printf("Configuration:\n"		"  -c probe_count %d\n"		"  -d (debug)     %d\n"		"  -g goodness    %d\n"		"  -h hostname    %s\n"		"  -i interval    %d\n"		"  -l live        %d\n"		"  -p local_port  %d\n"		"  -q min_delay   %f\n"		"  -s set_clock   %d\n"		"  -x cross_check %d\n",		ntpc.probe_count, debug, ntpc.goodness,		hostname, ntpc.cycle_time, ntpc.live, udp_local_port, min_delay,		ntpc.set_clock, ntpc.cross_check );	}	/* Startup sequence */	if ((usd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1)		{perror ("socket");exit(1);}	setup_receive(usd, INADDR_ANY, udp_local_port);	setup_transmit(usd, hostname, NTP_PORT, &ntpc);	primary_loop(usd, &ntpc);	close(usd);	return 0;}

⌨️ 快捷键说明

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