티스토리 뷰

???/소켓프로그래밍

타임 클라

BulGoGuMa 2009.07.14 09:28
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>	/* system data types */
/* #include <sys/stat.h> */
#include <sys/socket.h>	/* network */
#include <sys/time.h>	/* get/set precise time */
#include <netinet/in.h>	/* internet structures */
#include <netdb.h>	/* get IP from hostname */

#define IN_T_PORT 37

/* typedef uint32_t in_addr_t; /* some Linux versions need it */

in_addr_t get_ip_by_name(char *hostname) {
	struct hostent *he;
	if((he=gethostbyname(hostname))==NULL)
		{ herror(hostname); return -1; }
	else return *(in_addr_t *)he->h_addr;
}

void fill_sa_in(struct sockaddr_in *sai, in_addr_t addr,unsigned short port) {
	sai->sin_family=AF_INET; sai->sin_port=htons(port);
	sai->sin_addr.s_addr=addr;
	memset(sai->sin_zero,0,sizeof(sai->sin_zero));
}

void show_ip_and_port(struct sockaddr_in *in) {
	typedef unsigned char byte;
	char buf[64];
	sprintf(buf,"\n\n=== request from %u.%u.%u.%u:%u ===\n",
		((byte *)&in->sin_addr.s_addr)[0],
		((byte *)&in->sin_addr.s_addr)[1],
		((byte *)&in->sin_addr.s_addr)[2],
		((byte *)&in->sin_addr.s_addr)[3],
		ntohs(in->sin_port));
	write(1, buf, strlen(buf));
}

struct sockaddr_in ts_in,rp_in; char *es;

int net_init(char *host, int tl) {
	in_addr_t ip; int sk;

	/* ask DNS for the server address */
	alarm(tl); ip=get_ip_by_name(host); alarm(0);
	if((ip)==-1) { es="nslook"; return -1; }

	/* setup IP address, open socket... */
	fill_sa_in(&ts_in,ip,IN_T_PORT);
	if((sk=socket(AF_INET,SOCK_DGRAM,0))==-1)
		{ es="socket"; return -1; }

/*	show_ip_and_port(&ts_in);	*/
	return sk;
}

unsigned long ask_time(int sk, int tl) {
	socklen_t fl; long nt; alarm(tl);
	if(sendto(sk, NULL, 0, MSG_DONTROUTE | MSG_DONTWAIT,
		(struct sockaddr *)&ts_in, sizeof(ts_in))==-1)
			{ es="send"; goto err; }
	do {	fl=sizeof(rp_in);
		if(recvfrom(sk, &nt, sizeof(nt), 0,
			(struct sockaddr *)&rp_in, &fl)==-1)
				{ es="recv"; goto err; }
	} while (memcmp(&rp_in,&ts_in,sizeof(rp_in))!=0);
	alarm(0); return ntohl(nt)-2208988800UL;
err:	alarm(0); return 0;
}

int comp_time(int sk, int tl, double *td0, double *td1) {
	struct timeval tv0,tv1; long nt;

	gettimeofday(&tv0,NULL);/* ask time from local host */
	nt=ask_time(sk,2);	/* ask time from remote server, timeout=2 seconds */
	gettimeofday(&tv1,NULL);/* ask time from local host */

	if(nt==0) return -1;
	*td0=	tv0.tv_sec-nt+tv0.tv_usec*0.000001;
	*td1=	tv1.tv_sec-nt+tv1.tv_usec*0.000001;
	return 0;
}

char	usage[]="Usage: %s {-q|-s}[times] host-with-in.timed-service\n"
		"\t-q means query, -s set time from the server;\n"
		"\t'times' specifies how many times to repeat.\n"
		"Example: '%s -q5 my.time.server.net' queries 5 times.\n";

int main(int ac, char **av) {
	int sk,rep; double td0,td1;

	/* if no args display usage info */
	if(ac!=3 || av[1][0]!='-'
	|| ((sk=av[1][1])!='q' && sk!='s')) {
		es=strrchr(av[0],'/');
		if(es==NULL) es=av[0]; else es++;
		fprintf(stderr,usage,es,es); return -1;
	}
	rep=0; sscanf(av[1]+2,"%u",&rep);

	/* initialize network, timeout=120 seconds */
	sk=net_init(av[2],120);

	/* get and compare time as many times as requested */
	do {	comp_time(sk,2,&td0,&td1);
		printf("local-remote time=%12.6lf/%12.6lf\n",td0,td1);
	} while(--rep>0);

	close(sk); return 0;
err:	fprintf(stderr,"in.timed client: "); perror(es); return -1;
}

'??? > 소켓프로그래밍' 카테고리의 다른 글

타임 클라  (2) 2009.07.14
UDP TimeServer  (0) 2009.07.14
댓글
  • 프로필사진 HiKi 허어..goto쓰셨네요...
    암묵적으로 goto는 쓰지말라고 하죠 ㅎㅎ
    편하긴 하지만 인터프리터 방식의 언어에선 저게 쥐약이 될 수 있답니다.
    2009.07.27 18:27
  • 프로필사진 Favicon of https://bulgoguma.tistory.com BlogIcon BulGoGuMa 헐.. 그런건가요.. ;ㅅ;),,,
    코딩법을 바꿔야할... llorz,,
    2009.07.27 22:16 신고
댓글쓰기 폼