home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
nisttime.carsoncity.k12.mi.us
/
nisttime.carsoncity.k12.mi.us.tar
/
nisttime.carsoncity.k12.mi.us
/
pub
/
daytime
/
tcp_port37_client.c
< prev
next >
Wrap
C/C++ Source or Header
|
2004-05-03
|
10KB
|
287 lines
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>
main(argc,argv)
int argc;
char *argv[];
{
/*
client process to connect to the time service via port 37.
The client process uses the time message received to check (and
optionally to set) the time of the local clock. the comparison
assumes that the local clock keeps time in seconds from 1/1/70
which is the UNIX standard, and it computes the time difference
by converting the received time from seconds since 1900.0 to
seconds since 1/1/70. If the local machine keeps time in some
other way, then the comparison method will have to change, but
the rest should be okay.
This software was developed with US Government support
and it may not be sold, restricted or licensed. You
may duplicate this program provided that this notice
remains in all of the copies, and you may give it to
others provided they understand and agree to this
condition.
This program and the time protocol it uses are under
development and the implementation may change without
notice.
For questions or additional information, contact:
Judah Levine
Time and Frequency Division
NIST/847
325 Broadway
Boulder, Colorado 80305
(303) 492 7785
jlevine@boulder.nist.gov
*/
long int address; /* holds ip address */
int pserv = 37; /* time port number on server */
char *cp; /* server address in . notation */
char *sp; /* temporary for server address*/
int aindots[4]; /* numerical host address in dot notation*/
char addrbuf[20]; /* address formatted into dot notation*/
int j;
struct sockaddr_in sin; /* socket address structure */
int s; /* socket number */
int length; /* size of message */
unsigned long int xxy; /* holds received time*/
struct timeval tvv; /* holds local time */
long int diff; /* time difference, local - NIST */
char cc;
int stat;
int sw(); /*parses command-line switches*/
char let; /*command-line letter*/
long int val; /*command line value*/
struct hostent *serv0; /*pointer to structure returned by gethost */
/*
the following variables define what this program
should do and what output should be produced. The
values below are the defaults which may be changed
by characters on the command line as described below.
The effect of each variable is as follows:
Command-Line Switch effect
-m0 msg = 0 Do not produce any messages;
only time difference is written to
standard output.
-m1 or -M = 1 Produce messages.
-s0 set = 0 Do not adjust local time.
-s1 or -S = 1 Adjust local time without asking
-s2 = 2 Ask operator first.
-u<j> use server number j, where j is the index number
of the NIST server chosen from the following list.
the first server on the list is number 1, the
second is number 2, etc.
the default is to use the first server, which
is number 1.
note that the array uses C indexing, so that the
first entry in the array is number 0, etc.
thus any user response is decremented before
being used.
-u0 the name of the server is given as the next
parameter on the command line. the name can
be either a name or an ip address in dot
notation. The entry will be taken as a name
if the first non-blank character is not a
digit.
*/
int msg =1; /*default is short messages */
int set =2; /*default is ask before setting clock */
int use_serv=0; /*use first server by default*/
/*
the following is a list of the servers operated by
NIST. All of them will support the daytime protocol
in the format that this program expects.
Each server may be specified either by name, as in
time.nist.gov or by ip as in 192.43.244.18. If the
first character of the specification is a digit, then
the numerical format is assumed. If a name is entered,
it is converted to the corresponding ip address using
the standard DNS query. The program will fail if the
DNS query cannot find the ip number of the server
For more information about these servers, look at the
entry for the Internet Time Service on the Time and
Frequency Division homepage at www.boulder.nist.gov/timefreq
*/
#define NUMSRV 15
char *serv_ip[NUMSRV]= {"64.236.96.53" ,/*nist1.aol-va.truetime.com*/
"128.138.140.44" ,/*utcnist.colorado.edu*/
"207.200.81.113" ,/*nist1.aol-ca.truetime.com*/
"216.200.93.8" ,/*nist1-dc.glassey.com*/
"63.149.208.50" ,/*nist1.datum.com*/
"208.184.49.9" ,/*nist1-ny.glassey.com*/
"207.126.103.204",/*nist1-sj.glassey.com*/
"129.6.15.28" ,/*time-a.nist.gov*/
"129.6.15.29" ,/*time-b.nist.gov*/
"132.163.4.101" ,/*time-a.timefreq.bldrdoc.gov*/
"132.163.4.102" ,/*time-b.timefreq.bldrdoc.gov*/
"132.163.4.103" ,/*time-c.timefreq.bldrdoc.gov*/
"192.43.244.18" ,/*time.nist.gov*/
"131.107.1.10" , /*time-nw.nist.gov*/
"utcnist.colorado.edu" /*DNS entry= 128.138.140.44*/
};
/*
parse command line
*/
while( sw(argc,argv,&let,&val) != 0) /*switch is present*/
{
switch(let)
{
case 'm':
msg=val;
break;
case 's':
set=val;
break;
case 'S':
set=1;
break;
case 'M':
msg=1;
break;
case 'u':
if(val == 0) /*next parameter specifies server*/
{
argc--;
argv++; /*skip over the switch*/
if(argc <= 1)
{
printf("\n Expected server name is missing.\n\n");
exit();
}
cp=argv[1]; /*save the next parameter as the server name*/
use_serv=999; /*set flag*/
break;
}
/* server 1 has internal index 0 */
use_serv=val-1;
/* check if entry is out of range*/
if(use_serv < 0) use_serv=0;
if(use_serv >= NUMSRV) use_serv=NUMSRV - 1;
break;
default:
fprintf(stderr,"\nSwitch %c not recognized.",let);
break;
}
argc--; /*decrement argument counter */
argv++; /*and increment pointer */
}
/*
internet address of selected server
*/
if(use_serv != 999) cp=serv_ip[use_serv];
if(!isdigit(*cp)) /*first char not a digit, must convert name*/
{
if( (serv0=gethostbyname(cp)) == NULL)
{
printf("\n Cannot resolve name %s",cp);
exit();
}
if(serv0->h_length != 4)
{
printf("\nLength of host address (= %d) is wrong, 4 expected.",
serv0->h_length);
exit();
}
sp= serv0->h_addr_list[0];
for(j=0; j<4; j++) /*store and convert address*/
{
aindots[j]= *(sp++);
aindots[j] &= 0xff; /*turn off sign extension*/
}
sprintf(addrbuf,"%d.%d.%d.%d",
aindots[0],aindots[1],aindots[2],aindots[3]);
cp= addrbuf;
}
printf("\n Using server at address %s",cp);
/*
convert address to internal format
*/
if( (address=inet_addr(cp) ) == -1)
{
fprintf(stderr,"\n Internet address error.");
exit(1);
}
bzero( (char *)&sin,sizeof(sin));
sin.sin_addr.s_addr=address;
sin.sin_family=AF_INET;
sin.sin_port=htons(pserv);
/*
create the socket and then connect to the server
note that this is a stream socket and that record
boundaries are not preserved.
*/
if( (s=socket(AF_INET,SOCK_STREAM,0) ) < 0)
{
fprintf(stderr,"\n Socket creation error.");
exit(1);
}
if(connect(s, (struct sockaddr *) &sin, sizeof(sin) ) < 0)
{
perror(" time server Connect failed --");
exit(1);
}
length=read(s,&xxy,4); /*read 32 bit time value */
gettimeofday(&tvv,0); /*get time as soon as read completes*/
if(length <= 0)
{
perror(" No response from server ");
close(s);
exit(1);
}
xxy= ntohl(xxy); /*convert to local byte order*/
xxy -= 2208988800l; /*subtract 1970.0 - 1900.0*/
if(msg != 0) printf("\n Time value received = %lu",xxy);
diff= tvv.tv_sec - xxy;
if(tvv.tv_usec > 500000l) diff++; /*round up difference*/
if(msg != 0) printf("\n Local clock - NIST= %ld seconds.",diff);
else printf("%ld",diff);
close(s);
if(diff == 0)
{
if(msg != 0) printf("\n No adjustment is needed.\n");
exit();
}
if(set == 0) exit(); /*never adjust the time*/
if(set == 2) /*ask before doing anything*/
{
printf("\n Do you want to adjust the local clock ? [y/n] ");
cc=getchar();
}
if( (set == 1) || (cc == 'y') || (cc == 'Y') )
{
if(diff > 2100l)
{
if(msg != 0) printf("\n Adjustment limited to -2100 s.");
diff= 2100l;
}
if(diff < -2100l)
{
if(msg != 0) printf("\n Adjustment limited to +2100 s.");
diff= -2100l;
}
tvv.tv_sec= -diff;
tvv.tv_usec = 0;
stat=adjtime(&tvv,(struct timeval *) 0);
if(stat == 0) printf("\n Adjustment was performed.\n");
else perror("Adjustment failed. ");
}
exit();
}