1 /* newsresp.c - EUnet - bilse */
4 * From: Koen De Vleeschauwer <koen@eu.net>
5 * Subject: Re: innfeed-users: innfeed: measuring server response time
6 * To: jeff.garzik@spinne.com (Jeff Garzik)
7 * Date: Tue, 13 May 1997 16:33:27 +0200 (MET DST)
8 * Cc: innfeed-users@vix.com
10 * > Is there an easy way to measure server response time, and print it out
11 * > on the innfeed status page? Cyclone's nntpTime measures login banner
12 * > response time and an article add and lookup operation.
14 * > It seems to me that innfeed could do something very similar. It could
15 * > very easily sample gettimeofday() or Time.Now to determine a remote
16 * > server's average response time for lookups, lookup failures, article
17 * > send throughput, whatever.
19 * > These statistics might be invaluable to developers creating advanced
20 * > connection and article delivery algorithms. If I knew, for example,
21 * > that a site's article send/save throughput was really fast, but history
22 * > lookups were really slow, my algorithm could reserve a channel or two
23 * > for TAKETHIS-only use.
25 * We use a stand-alone program which opens up an additional nntp channel
26 * from time to time and takes a peek at the various response times.
27 * It's also interesting to tune one's own box.
28 * I've included the source code; please consider this supplied 'as is';
29 * bugs and features alike. SunOS, Solaris and Irix ought to be ok;
30 * eg. gcc -traditional -o newsresp ./newsresp.c -lnsl -lsocket on S0laris.
31 * If a host has an uncommonly long banner you may have to change a constant
32 * somewhere; forget. Please note one has to interpret the output;
33 * eg. whether one is measuring rtt or history lookup time.
36 * news 1 % newsresp -n 5 news.eu.net
37 * ---------------------------------
38 * news.eu.net is 134.222.90.2 port 119
40 * 0.0 0.0 Connecting ...
41 * 0.0 0.0 OK, waiting for prompt
42 * 0.0 0.0 <<< 200 EU.net InterNetNews server INN 1.5.1 17-Dec-1996 re [...]
43 * 0.0 0.0 >>> ihave <244796399@a>
46 * 0.0 0.0 <<< 437 Empty article
47 * 0.0 0.0 >>> ihave <244796398@a>
50 * 0.0 0.0 <<< 437 Empty article
51 * 0.0 0.0 >>> ihave <244796397@a>
54 * 0.0 0.0 <<< 437 Empty article
55 * 0.0 0.0 >>> ihave <244796396@a>
58 * 0.1 0.0 <<< 437 Empty article
59 * 0.1 0.0 >>> ihave <244796395@a>
62 * 0.1 0.0 <<< 437 Empty article
68 #include <sys/types.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
76 struct sockaddr_in sock_in;
90 struct protoent *tcp_proto;
93 while ( (c = getopt(argc,argv,"n:")) != -1 )
95 case 'n': sscanf(optarg,"%u",&numart); break;
98 if ( numart == 0 || optind == argc )
101 fprintf(stderr,"Usage: %s [-n articles] host ...\n",argv[0]);
105 if ( (tcp_proto = getprotobyname("tcp")) == 0 )
106 fatal("getprotobyname");
107 for ( whoP = argv+optind; *whoP != 0; whoP++ ) {
108 if ( (sock = socket(PF_INET,SOCK_STREAM,tcp_proto->p_proto)) < 0 )
110 temp = inet_addr(*whoP);
111 if ( temp != (unsigned long) -1 ) {
112 sock_in.sin_addr.s_addr = temp;
113 sock_in.sin_family = AF_INET;
116 host = gethostbyname(*whoP);
118 sock_in.sin_family = host->h_addrtype;
119 memcpy(&sock_in.sin_addr,host->h_addr,host->h_length);
122 fprintf(stderr,"gethostbyname can't find %s\n",*whoP);
126 sock_in.sin_port = htons(NNTPPORT);
127 printf("---------------------------------\n%s is %s port %d\n",
128 *whoP,inet_ntoa(sock_in.sin_addr),ntohs(sock_in.sin_port));
137 ptime(); fflush(stdout);
151 printf("Expected %s, bailing out.\n",how);
161 unsigned do_time(start)
166 gettimeofday(&now,(struct timezone *)0);
167 return ( now.tv_sec*1000 + now.tv_usec/1000 - start );
171 unsigned start, elapsed, diff;
176 elapsed = do_time(start);
177 diff = elapsed - diff;
178 printf("%5.1f %5.1f ",((float)elapsed)/1000.0,((float)diff)/1000.0);
181 massagebuff(bread,buf)
188 strcpy(buf+55," [...]\n");
191 for ( p = buf; *p != '\0'; )
192 if ( *p != '\r' ) /* We like to do it RISC style. */
203 static char ihave[32],
206 struct timeval start_tv;
209 printf(" elap diff\n");
211 gettimeofday(&start_tv,(struct timezone *)0);
212 start = start_tv.tv_sec*1000 + start_tv.tv_usec/1000;
215 printf("Connecting ...\n");
216 if ( connect(sock,(struct sockaddr*)&sock_in,sizeof(sock_in)) < 0 ) {
221 printf("OK, waiting for prompt\n");
223 if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) {
224 error("read socket");
227 massagebuff(bread,buf);
229 printf("<<< %s",buf);
230 if ( strncmp(buf,"200",3) != 0 && strncmp(buf,"201",3) != 0 ) {
231 ierror("200 or 201",buf);
236 snprintf(ihave,sizeof(ihave),"ihave <%u@a>\r\n",start+numart);
238 printf(">>> %s",ihave);
239 if ( write(sock,ihave,strlen(ihave)) != strlen(ihave) ) {
240 error("write socket");
244 if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) {
245 error("read socket");
248 massagebuff(bread,buf);
250 printf("<<< %s",buf);
251 if ( strncmp(buf,"335",3) != 0 && strncmp(buf,"435",3) != 0 ) {
252 ierror("335 or 435 ",buf);
256 if ( strncmp(buf,"335",3) == 0 ) {
258 printf(">>> %s",dot);
259 if ( write(sock,dot,sizeof(dot)-1) != sizeof(dot)-1 ) {
260 error("write socket");
264 if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) {
265 error("read socket");
268 massagebuff(bread,buf);
270 printf("<<< %s",buf);
271 if ( strncmp(buf,"437",3) != 0 && strncmp(buf,"235",3) != 0 ) {
272 ierror("437 or 235",buf);
276 } while ( --numart != 0 );
279 printf(">>> %s",quit);
280 if ( write(sock,quit,sizeof(quit)-1) != sizeof(quit)-1 ) {
281 error("write socket");
285 if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) {
286 error("read socket");
289 massagebuff(bread,buf);
291 printf("<<< %s",buf);
292 if ( strncmp(buf,"205",3) != 0 ) {