webbench

socket.c

 1 /* $Id: socket.c 1.1 1995/01/01 07:11:14 cthuang Exp $
 2  *
 3  * This module has been modified by Radim Kolar for OS/2 emx
 4  */
 5 
 6 /***********************************************************************
 7   module:       socket.c
 8   program:      popclient
 9   SCCS ID:      @(#)socket.c    1.5  4/1/94
10   programmer:   Virginia Tech Computing Center
11   compiler:     DEC RISC C compiler (Ultrix 4.1)
12   environment:  DEC Ultrix 4.3 
13   description:  UNIX sockets code.
14  ***********************************************************************/
15  
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <fcntl.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <netdb.h>
22 #include <sys/time.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 
29 int Socket(const char *host, int clientPort)
30 {
31     int sock;
32     unsigned long inaddr;
33     struct sockaddr_in ad;
34     struct hostent *hp;
35     
36     memset(&ad, 0, sizeof(ad));
37     ad.sin_family = AF_INET;
38 
39     inaddr = inet_addr(host);
40     if (inaddr != INADDR_NONE)
41         memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
42     else
43     {
44         hp = gethostbyname(host);
45         if (hp == NULL)
46             return -1;
47         memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
48     }
49     ad.sin_port = htons(clientPort);
50     
51     sock = socket(AF_INET, SOCK_STREAM, 0);
52     if (sock < 0)
53         return sock;
54     if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0)
55         return -1;
56     return sock;
57 }
View Code

webbench.c

 

  1 /*
  2  * (C) Radim Kolar 1997-2004
  3  * This is free software, see GNU Public License version 2 for
  4  * details.
  5  *
  6  * Simple forking WWW Server benchmark:
  7  *
  8  * Usage:
  9  *   webbench --help
 10  *
 11  * Return codes:
 12  *    0 - sucess
 13  *    1 - benchmark failed (server is not on-line)
 14  *    2 - bad param
 15  *    3 - internal error, fork failed
 16  * 
 17  */ 
 18 #include "socket.c"
 19 #include <unistd.h>
 20 #include <sys/param.h>
 21 #include <rpc/types.h>
 22 #include <getopt.h>
 23 #include <strings.h>
 24 #include <time.h>
 25 #include <signal.h>
 26 
 27 /* values */
 28 volatile int timerexpired=0;
 29 int speed=0;
 30 int failed=0;
 31 int bytes=0;
 32 /* globals */
 33 int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */
 34 /* Allow: GET, HEAD, OPTIONS, TRACE */
 35 #define METHOD_GET 0
 36 #define METHOD_HEAD 1
 37 #define METHOD_OPTIONS 2
 38 #define METHOD_TRACE 3
 39 #define PROGRAM_VERSION "1.5"
 40 int method=METHOD_GET;
 41 int clients=1;
 42 int force=0;
 43 int force_reload=0;
 44 int proxyport=80;
 45 char *proxyhost=NULL;
 46 int benchtime=30;
 47 /* internal */
 48 int mypipe[2];
 49 char host[MAXHOSTNAMELEN];
 50 #define REQUEST_SIZE 2048
 51 char request[REQUEST_SIZE];
 52 
 53 static const struct option long_options[]=
 54 {
 55  {"force",no_argument,&force,1},
 56  {"reload",no_argument,&force_reload,1},
 57  {"time",required_argument,NULL,'t'},
 58  {"help",no_argument,NULL,'?'},
 59  {"http09",no_argument,NULL,'9'},
 60  {"http10",no_argument,NULL,'1'},
 61  {"http11",no_argument,NULL,'2'},
 62  {"get",no_argument,&method,METHOD_GET},
 63  {"head",no_argument,&method,METHOD_HEAD},
 64  {"options",no_argument,&method,METHOD_OPTIONS},
 65  {"trace",no_argument,&method,METHOD_TRACE},
 66  {"version",no_argument,NULL,'V'},
 67  {"proxy",required_argument,NULL,'p'},
 68  {"clients",required_argument,NULL,'c'},
 69  {NULL,0,NULL,0}
 70 };
 71 
 72 /* prototypes */
 73 static void benchcore(const char* host,const int port, const char *request);
 74 static int bench(void);
 75 static void build_request(const char *url);
 76 
 77 static void alarm_handler(int signal)
 78 {
 79    timerexpired=1;
 80 }    
 81 
 82 static void usage(void)
 83 {
 84    fprintf(stderr,
 85     "webbench [option]... URL\n"
 86     "  -f|--force               Don't wait for reply from server.\n"
 87     "  -r|--reload              Send reload request - Pragma: no-cache.\n"
 88     "  -t|--time <sec>          Run benchmark for <sec> seconds. Default 30.\n"
 89     "  -p|--proxy <server:port> Use proxy server for request.\n"
 90     "  -c|--clients <n>         Run <n> HTTP clients at once. Default one.\n"
 91     "  -9|--http09              Use HTTP/0.9 style requests.\n"
 92     "  -1|--http10              Use HTTP/1.0 protocol.\n"
 93     "  -2|--http11              Use HTTP/1.1 protocol.\n"
 94     "  --get                    Use GET request method.\n"
 95     "  --head                   Use HEAD request method.\n"
 96     "  --options                Use OPTIONS request method.\n"
 97     "  --trace                  Use TRACE request method.\n"
 98     "  -?|-h|--help             This information.\n"
 99     "  -V|--version             Display program version.\n"
100     );
101 };
102 int main(int argc, char *argv[])
103 {
104  int opt=0;
105  int options_index=0;
106  char *tmp=NULL;
107 
108  if(argc==1)
109  {
110       usage();
111           return 2;
112  } 
113 
114  while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF )
115  {
116   switch(opt)
117   {
118    case  0 : break;
119    case 'f': force=1;break;
120    case 'r': force_reload=1;break; 
121    case '9': http10=0;break;
122    case '1': http10=1;break;
123    case '2': http10=2;break;
124    case 'V': printf(PROGRAM_VERSION"\n");exit(0);
125    case 't': benchtime=atoi(optarg);break;         
126    case 'p': 
127          /* proxy server parsing server:port */
128          tmp=strrchr(optarg,':');
129          proxyhost=optarg;
130          if(tmp==NULL)
131          {
132              break;
133          }
134          if(tmp==optarg)
135          {
136              fprintf(stderr,"Error in option --proxy %s: Missing hostname.\n",optarg);
137              return 2;
138          }
139          if(tmp==optarg+strlen(optarg)-1)
140          {
141              fprintf(stderr,"Error in option --proxy %s Port number is missing.\n",optarg);
142              return 2;
143          }
144          *tmp='\0';
145          proxyport=atoi(tmp+1);break;
146    case ':':
147    case 'h':
148    case '?': usage();return 2;break;
149    case 'c': clients=atoi(optarg);break;
150   }
151  }
152  
153  if(optind==argc) {
154                       fprintf(stderr,"webbench: Missing URL!\n");
155               usage();
156               return 2;
157                     }
158 
159  if(clients==0) clients=1;
160  if(benchtime==0) benchtime=60;
161  /* Copyright */
162  fprintf(stderr,"Webbench - Simple Web Benchmark "PROGRAM_VERSION"\n"
163      "Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.\n"
164      );
165  build_request(argv[optind]);
166  /* print bench info */
167  printf("\nBenchmarking: ");
168  switch(method)
169  {
170      case METHOD_GET:
171      default:
172          printf("GET");break;
173      case METHOD_OPTIONS:
174          printf("OPTIONS");break;
175      case METHOD_HEAD:
176          printf("HEAD");break;
177      case METHOD_TRACE:
178          printf("TRACE");break;
179  }
180  printf(" %s",argv[optind]);
181  switch(http10)
182  {
183      case 0: printf(" (using HTTP/0.9)");break;
184      case 2: printf(" (using HTTP/1.1)");break;
185  }
186  printf("\n");
187  if(clients==1) printf("1 client");
188  else
189    printf("%d clients",clients);
190 
191  printf(", running %d sec", benchtime);
192  if(force) printf(", early socket close");
193  if(proxyhost!=NULL) printf(", via proxy server %s:%d",proxyhost,proxyport);
194  if(force_reload) printf(", forcing reload");
195  printf(".\n");
196  return bench();
197 }
198 
199 void build_request(const char *url)
200 {
201   char tmp[10];
202   int i;
203 
204   bzero(host,MAXHOSTNAMELEN);
205   bzero(request,REQUEST_SIZE);
206 
207   if(force_reload && proxyhost!=NULL && http10<1) http10=1;
208   if(method==METHOD_HEAD && http10<1) http10=1;
209   if(method==METHOD_OPTIONS && http10<2) http10=2;
210   if(method==METHOD_TRACE && http10<2) http10=2;
211 
212   switch(method)
213   {
214       default:
215       case METHOD_GET: strcpy(request,"GET");break;
216       case METHOD_HEAD: strcpy(request,"HEAD");break;
217       case METHOD_OPTIONS: strcpy(request,"OPTIONS");break;
218       case METHOD_TRACE: strcpy(request,"TRACE");break;
219   }
220           
221   strcat(request," ");
222 
223   if(NULL==strstr(url,"://"))
224   {
225       fprintf(stderr, "\n%s: is not a valid URL.\n",url);
226       exit(2);
227   }
228   if(strlen(url)>1500)
229   {
230          fprintf(stderr,"URL is too long.\n");
231      exit(2);
232   }
233   if(proxyhost==NULL)
234        if (0!=strncasecmp("http://",url,7)) 
235        { fprintf(stderr,"\nOnly HTTP protocol is directly supported, set --proxy for others.\n");
236              exit(2);
237            }
238   /* protocol/host delimiter */
239   i=strstr(url,"://")-url+3;
240   /* printf("%d\n",i); */
241 
242   if(strchr(url+i,'/')==NULL) {
243                                 fprintf(stderr,"\nInvalid URL syntax - hostname don't ends with '/'.\n");
244                                 exit(2);
245                               }
246   if(proxyhost==NULL)
247   {
248    /* get port from hostname */
249    if(index(url+i,':')!=NULL &&
250       index(url+i,':')<index(url+i,'/'))
251    {
252        strncpy(host,url+i,strchr(url+i,':')-url-i);
253        bzero(tmp,10);
254        strncpy(tmp,index(url+i,':')+1,strchr(url+i,'/')-index(url+i,':')-1);
255        /* printf("tmp=%s\n",tmp); */
256        proxyport=atoi(tmp);
257        if(proxyport==0) proxyport=80;
258    } else
259    {
260      strncpy(host,url+i,strcspn(url+i,"/"));
261    }
262    // printf("Host=%s\n",host);
263    strcat(request+strlen(request),url+i+strcspn(url+i,"/"));
264   } else
265   {
266    // printf("ProxyHost=%s\nProxyPort=%d\n",proxyhost,proxyport);
267    strcat(request,url);
268   }
269   if(http10==1)
270       strcat(request," HTTP/1.0");
271   else if (http10==2)
272       strcat(request," HTTP/1.1");
273   strcat(request,"\r\n");
274   if(http10>0)
275       strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"\r\n");
276   if(proxyhost==NULL && http10>0)
277   {
278       strcat(request,"Host: ");
279       strcat(request,host);
280       strcat(request,"\r\n");
281   }
282   if(force_reload && proxyhost!=NULL)
283   {
284       strcat(request,"Pragma: no-cache\r\n");
285   }
286   if(http10>1)
287       strcat(request,"Connection: close\r\n");
288   /* add empty line at end */
289   if(http10>0) strcat(request,"\r\n"); 
290   // printf("Req=%s\n",request);
291 }
292 
293 /* vraci system rc error kod */
294 static int bench(void)
295 {
296   int i,j,k;    
297   pid_t pid=0;
298   FILE *f;
299 
300   /* check avaibility of target server */
301   i=Socket(proxyhost==NULL?host:proxyhost,proxyport);
302   if(i<0) { 
303        fprintf(stderr,"\nConnect to server failed. Aborting benchmark.\n");
304            return 1;
305          }
306   close(i);
307   /* create pipe */
308   if(pipe(mypipe))
309   {
310       perror("pipe failed.");
311       return 3;
312   }
313 
314   /* not needed, since we have alarm() in childrens */
315   /* wait 4 next system clock tick */
316   /*
317   cas=time(NULL);
318   while(time(NULL)==cas)
319         sched_yield();
320   */
321 
322   /* fork childs */
323   for(i=0;i<clients;i++)
324   {
325        pid=fork();
326        if(pid <= (pid_t) 0)
327        {
328            /* child process or error*/
329                sleep(1); /* make childs faster */
330            break;
331        }
332   }
333 
334   if( pid< (pid_t) 0)
335   {
336           fprintf(stderr,"problems forking worker no. %d\n",i);
337       perror("fork failed.");
338       return 3;
339   }
340 
341   if(pid== (pid_t) 0)
342   {
343     /* I am a child */
344     if(proxyhost==NULL)
345       benchcore(host,proxyport,request);
346          else
347       benchcore(proxyhost,proxyport,request);
348 
349          /* write results to pipe */
350      f=fdopen(mypipe[1],"w");
351      if(f==NULL)
352      {
353          perror("open pipe for writing failed.");
354          return 3;
355      }
356      /* fprintf(stderr,"Child - %d %d\n",speed,failed); */
357      fprintf(f,"%d %d %d\n",speed,failed,bytes);
358      fclose(f);
359      return 0;
360   } else
361   {
362       f=fdopen(mypipe[0],"r");
363       if(f==NULL) 
364       {
365           perror("open pipe for reading failed.");
366           return 3;
367       }
368       setvbuf(f,NULL,_IONBF,0);
369       speed=0;
370           failed=0;
371           bytes=0;
372 
373       while(1)
374       {
375           pid=fscanf(f,"%d %d %d",&i,&j,&k);
376           if(pid<2)
377                   {
378                        fprintf(stderr,"Some of our childrens died.\n");
379                        break;
380                   }
381           speed+=i;
382           failed+=j;
383           bytes+=k;
384           /* fprintf(stderr,"*Knock* %d %d read=%d\n",speed,failed,pid); */
385           if(--clients==0) break;
386       }
387       fclose(f);
388 
389   printf("\nSpeed=%d pages/min, %d bytes/sec.\nRequests: %d susceed, %d failed.\n",
390           (int)((speed+failed)/(benchtime/60.0f)),
391           (int)(bytes/(float)benchtime),
392           speed,
393           failed);
394   }
395   return i;
396 }
397 
398 void benchcore(const char *host,const int port,const char *req)
399 {
400  int rlen;
401  char buf[1500];
402  int s,i;
403  struct sigaction sa;
404 
405  /* setup alarm signal handler */
406  sa.sa_handler=alarm_handler;
407  sa.sa_flags=0;
408  if(sigaction(SIGALRM,&sa,NULL))
409     exit(3);
410  alarm(benchtime);
411 
412  rlen=strlen(req);
413  nexttry:while(1)
414  {
415     if(timerexpired)
416     {
417        if(failed>0)
418        {
419           /* fprintf(stderr,"Correcting failed by signal\n"); */
420           failed--;
421        }
422        return;
423     }
424     s=Socket(host,port);                          
425     if(s<0) { failed++;continue;} 
426     if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;}
427     if(http10==0) 
428         if(shutdown(s,1)) { failed++;close(s);continue;}
429     if(force==0) 
430     {
431             /* read all available data from socket */
432         while(1)
433         {
434               if(timerexpired) break; 
435           i=read(s,buf,1500);
436               /* fprintf(stderr,"%d\n",i); */
437           if(i<0) 
438               { 
439                  failed++;
440                  close(s);
441                  goto nexttry;
442               }
443            else
444                if(i==0) break;
445                else
446                    bytes+=i;
447         }
448     }
449     if(close(s)) {failed++;continue;}
450     speed++;
451  }
452 }
View Code

 

Makefile

 1 CFLAGS?=    -Wall -ggdb -W -O
 2 CC?=        gcc
 3 LIBS?=
 4 LDFLAGS?=
 5 PREFIX?=    /usr/local
 6 VERSION=1.5
 7 TMPDIR=/tmp/webbench-$(VERSION)
 8 
 9 #all:   webbench tags
10 all:   webbench
11 
12 #tags:  *.c
13 #    -ctags *.c
14 
15 install: webbench
16     install -s webbench $(DESTDIR)$(PREFIX)/bin    
17     install -m 644 webbench.1 $(DESTDIR)$(PREFIX)/man/man1    
18     install -d $(DESTDIR)$(PREFIX)/share/doc/webbench
19     install -m 644 debian/copyright $(DESTDIR)$(PREFIX)/share/doc/webbench
20     install -m 644 debian/changelog $(DESTDIR)$(PREFIX)/share/doc/webbench
21 
22 webbench: webbench.o Makefile
23     $(CC) $(CFLAGS) $(LDFLAGS) -o webbench webbench.o $(LIBS) 
24 
25 clean:
26     -rm -f *.o webbench *~ core *.core
27 #    -rm -f *.o webbench *~ core *.core tags
28     
29 tar:   clean
30     -debian/rules clean
31     rm -rf $(TMPDIR)
32     install -d $(TMPDIR)
33     cp -p Makefile webbench.c socket.c webbench.1 $(TMPDIR)
34     install -d $(TMPDIR)/debian
35     -cp -p debian/* $(TMPDIR)/debian
36     ln -sf debian/copyright $(TMPDIR)/COPYRIGHT
37     ln -sf debian/changelog $(TMPDIR)/ChangeLog
38     -cd $(TMPDIR) && cd .. && tar cozf webbench-$(VERSION).tar.gz webbench-$(VERSION)
39 
40 webbench.o:    webbench.c socket.c Makefile
41 
42 .PHONY: clean install all tar
View Code

 

 

posted @ 2016-08-18 06:24  PKICA  阅读(270)  评论(0编辑  收藏  举报