"Disclaimer: Copyright, welcome reprint, please do not use for commercial purposes. Contact mailbox: feixiaoxing @163.com "
There's a lot of code on the Web for stress testing. However, I personally still think this webbench code is better, probably also because I prefer a small and refined code. Stress testing typically means that the server is subjected to a certain load, which in turn verifies server CPU utilization, IO speed, mem and swap sizes, responsiveness, server program stability, concurrency performance, and more.
Originally Webbench is composed of webbench.c and socket.c two files, here for the convenience of reading, I myself will two parts of the code together, in fact, is the same.
/* * (C) Radim Kolar 1997-2004 * This is the free software and see the GNU public License version 2 for * details. * Simple forking WWW Server Benchmark: * * Usage: * webbench--help * * Return Codes: * 0-sucess * 1-benchma RK failed (server is not on-line) * 2-bad param * 3-internal error, fork failed * */#include <SYS/TYPES.H&G T, #include <sys/socket.h> #include <fcntl.h> #include <netinet/in.h> #include <arpa/inet.h># Include <netdb.h> #include <sys/time.h> #include <string.h> #include <unistd.h> #include < stdio.h> #include <stdlib.h> #include <stdarg.h>int Socket (const char *host, int clientport) {int sock; unsigned long inaddr; struct sockaddr_in ad; struct Hostent *hp; memset (&ad, 0, sizeof (AD)); ad.sin_family = af_inet; INADDR = inet_addr (host); if (inaddr! = Inaddr_none) memcpy (&ad.sin_addr, &inaddr, sizeof (INADDR)); else {hp = gethostbyname (host); if (HP = = NULL) return-1; memcpy (&ad.sin_addr, hp->h_addr, hp->h_length); } Ad.sin_port = Htons (ClientPort); Sock = socket (af_inet, sock_stream, 0); if (Sock < 0) return sock; if (Connect (sock, struct sockaddr *) &ad, sizeof (AD)) < 0) return-1; Return sock;} #include <unistd.h> #include <sys/param.h> #include <rpc/types.h> #include <getopt.h> #include <strings.h> #include <time.h> #include <signal.h>/* values */volatile int timerexpired=0;int speed=0; int Failed=0;int bytes=0;/* globals */int http10=1; /* 0-http/0.9, 1-http/1.0, 2-http/1.1 *//* allow:get, HEAD, OPTIONS, TRACE */#define METHOD_GET 0#define Method_hea D 1#define method_options 2#define method_trace 3#define program_version "1.5" int method=method_get;int clients=1;int Force=0;int force_reload=0;int Proxyport=80;char *proxyhost=null;int benchtime=30;/* internal */int Mypipe[2];char Host[maxhostnameleN]; #define REQUEST_SIZE 2048char request[request_size];static const struct option long_options[]={{"Force", No_ argument,&force,1}, {"Reload", no_argument,&force_reload,1}, {"Time", Required_argument,null, ' t '}, {"Help", No_argument,null, '? '}, {"http09", No_argument,null, ' 9 '}, {"Http10", No_argument,null, ' 1 '}, {"Http11", No_argument, NULL, ' 2 '}, {"Get", No_argument,&method,method_get}, {"Head", No_argument,&method,method_head}, {"Options", No_argument,&method,method_options}, {"Trace", no_argument,&method,method_trace}, {"Version", No_argument, NULL, ' V '}, {"Proxy", Required_argument,null, ' P '}, {"Clients", Required_argument,null, ' C '}, {null,0,null,0}};/* Prototypes */static void Benchcore (const char* HOST,CONST int port, const char *request); static int bench (void); static voi D build_request (const char *url), static void Alarm_handler (int signal) {timerexpired=1;} static void usage (void) {fprintf (stderr, "webbench [option] ... Url\n ""-f|--force Don ' t wait for reply FRom server.\n ""-r|--reload Send Reload request-pragma:no-cache.\n ""-t|--time <sec> Run Benchmark for <sec> seconds. Default 30.\n ""-p|--proxy <server:port> use proxy server for request.\n ""-c|--clients <n> Run < N> HTTP clients at once. Default one.\n "" -9|--http09 use http/0.9 style requests.\n "" -1|--http10 use http/1.0 Protoco l.\n "" -2|--http11 use http/1.1 protocol.\n ""--get use GET request method.\n ""--head Use HEAD request method.\n ""--options Use options request Method.\n ""--trace Use TRACE request Method.\n ""-?| -h|--help this information.\n "", "-v|--version Display program version.\n"); int main (int argc, char *argv[]) {int opt=0; int options_index=0; char *tmp=null; if (argc==1) {usage (); return 2; } while ((Opt=getopt_long (ARGC,ARGV, "912vfrt:p:c:?h", Long_Options,&options_index)!=eof) {switch (opt) {case 0:break; Case ' F ': force=1;break; Case ' R ': Force_reload=1;break; Case ' 9 ': http10=0;break; Case ' 1 ': http10=1;break; Case ' 2 ': http10=2;break; Case ' V ': printf (program_version "\ n"); exit (0); Case ' t ': Benchtime=atoi (Optarg); Case ' P ':/* Proxy Server parsing Server:port */TMP=STRRCHR (Optarg, ': '); Proxyhost=optarg; if (tmp==null) {break; } if (Tmp==optarg) {fprintf (stderr, "Error in option--proxy%s:missing hostname.\n", Optarg); return 2; } if (Tmp==optarg+strlen (Optarg)-1) {fprintf (stderr, "Error in option--proxy%s Port number is missing.\n", opt ARG); return 2; } *tmp= ' + '; Proxyport=atoi (tmp+1); Case ': ': Case ' h ': Case '? ': usage (); return 2;break; Case ' C ': Clients=atoi (Optarg); }} if (OPTIND==ARGC) {fprintf (stderr, "webbench:missing url!\n"); Usage (); return 2; } if (clients==0) Clients=1; if (benchtime==0) benchtime=60; /* Copyright * * fprintf (stderr, "Webbench-simple Web Benchmark" program_version "\ n" "Copyright (c) Radim Kolar 1997-2004, GPL Open Source software.\n "); Build_request (Argv[optind]); /* Print Bench Info */printf ("\nbenchmarking:"); Switch (method) {case METHOD_GET:default:printf ("GET"), break, Case method_options:printf ("Options"); method_head:printf ("HEAD"); Case method_trace:printf ("TRACE"); } printf ("%s", Argv[optind]); Switch (HTTP10) {Case 0:printf ("(using http/0.9)"), break, Case 2:printf ("(using http/1.1)"), Break,} printf ("\ n"); if (clients==1) printf ("1 Client"); else printf ("%d clients", clients); printf (", Running%d sec", benchtime); if (force) printf (", Early socket Close"); if (proxyhost!=null) printf (", via Proxy server%s:%d", proxyhost,proxyport); if (force_reload) printf (", forcing Reload"); printf (". \ n"); return Bench ();} void Build_request (const char *url) {ChaR Tmp[10]; int i; Bzero (Host,maxhostnamelen); Bzero (request,request_size); if (force_reload && proxyhost!=null && http10<1) http10=1; if (method==method_head && http10<1) http10=1; if (method==method_options && http10<2) http10=2; if (method==method_trace && http10<2) http10=2; Switch (method) {Default:case method_get:strcpy (request, "GET"); Case method_head:strcpy (Request, "HEAD"); Case method_options:strcpy (Request, "OPTIONS"); Case method_trace:strcpy (Request, "TRACE"); } strcat (Request, ""); if (Null==strstr (URL, "://")) {fprintf (stderr, "\n%s:is not a valid url.\n", URL); Exit (2); } if (strlen (URL) >1500) {fprintf (stderr, "url is too long.\n"); exit (2); if (proxyhost==null) if (0!=strncasecmp ("http//", url,7)) {fprintf (stderr, "\nonly http protocol is directly suppor Ted, set--proxy for others.\n "); Exit (2); }/* Protocol/host delimiter */i=strSTR (URL, "://")-url+3; /* printf ("%d\n", I); */if (STRCHR (url+i, '/') ==null) {fprintf (stderr, "\ninvalid url syntax-hostname don ' t end s with '/'. \ n '); Exit (2); if (proxyhost==null) {/* get port from hostname */if (index (Url+i, ': ')!=null && index (url+i, ': ') <i Ndex (Url+i, '/')) {strncpy (HOST,URL+I,STRCHR (url+i, ': ')-url-i); Bzero (tmp,10); strncpy (Tmp,index (url+i, ': ') +1,strchr (url+i, '/')-index (Url+i, ': ')-1); /* printf ("tmp=%s\n", TMP); */Proxyport=atoi (TMP); if (proxyport==0) proxyport=80; } else {strncpy (host,url+i,strcspn (Url+i, "/")); }//printf ("host=%s\n", Host); strcat (Request+strlen (Request), url+i+strcspn (Url+i, "/")); } else {//printf ("proxyhost=%s\nproxyport=%d\n", Proxyhost,proxyport); strcat (Request,url); } if (http10==1) strcat (Request, "http/1.0"); else if (http10==2) strcat (Request, "http/1.1"); strcat (Request, "\ r \ n"); if (HTtp10>0) strcat (Request, "User-agent:webbench" program_version "\ r \ n"); if (proxyhost==null && http10>0) {strcat (Request, "Host:"); strcat (Request,host); strcat (Request, "\ r \ n"); } if (Force_reload && proxyhost!=null) {strcat (Request, "pragma:no-cache\r\n"); } if (http10>1) strcat (Request, "connection:close\r\n"); /* Add empty line at end */if (http10>0) strcat (Request, "\ r \ n"); printf ("req=%s\n", request);} /* VRACI system RC error kod */static int bench (void) {int i,j,k; pid_t pid=0; FILE *f; /* Check avaibility of target server */I=socket (proxyhost==null?host:proxyhost,proxyport); if (i<0) {fprintf (stderr, "\nconnect to server failed. Aborting benchmark.\n "); return 1; } close (i); /* Create pipe */if (pipe (mypipe)) {perror ("pipe failed."); return 3; }/* Not needed, since we had alarm () in childrens */* Wait 4 next system clock tick */* Cas=time (NULL); while (Time (NULL) ==cas) Sched_yield (); */* Fork Childs */for (i=0;i<clients;i++) {pid=fork (); if (PID <= (pid_t) 0) {/* child process or error*/sleep (1);/* Make childs faster */break; }} if (pid< (pid_t) 0) {fprintf (stderr, "problems forking worker No.%d\n", i); Perror ("Fork failed."); return 3; } if (pid== (pid_t) 0) {/* I am a child */if (proxyhost==null) Benchcore (host,proxyport,request); else Benchcore (proxyhost,proxyport,request); /* Write results to Pipe */F=fdopen (mypipe[1], "w"); if (f==null) {perror ("Open pipe for writing failed."); return 3;}/* fprintf (stderr, "child-%d%d\n", speed,failed); */fprintf (f, "%d%d%d\n", speed,failed,bytes); Fclose (f); return 0; } else {F=fdopen (mypipe[0], "R"); if (f==null) {perror ("Open pipe for reading failed."); return 3; } setvbuf (f,null,_ionbf,0); Speed=0; Failed=0; bytes=0; while (1) {pid=fscanf (F, "%d%d%d", &i,&j,&k); if (pid<2) {fprintf (stderr, "Some of our childrens died.\n"); Break } speed+=i; Failed+=j; Bytes+=k; /* fprintf (stderr, "*knock*%d%d read=%d\n", speed,failed,pid); */if (--clients==0) break; } fclose (f); printf ("\nspeed=%d pages/min,%d bytes/sec.\nrequests:%d susceed,%d failed.\n", (int) ((speed+failed)/(benchtime/ 60.0f)), (int) (bytes/(float) benchtime), speed, failed); } return i;} void Benchcore (const char *host,const int Port,const char *req) {int rlen; char buf[1500]; int s,i; struct sigaction sa; * Setup Alarm Signal Handler * * SA.SA_HANDLER=ALARM_HANDLER; sa.sa_flags=0; if (Sigaction (Sigalrm,&sa,null)) exit (3); Alarm (benchtime); Rlen=strlen (req); Nexttry:while (1) {if (timerexpired) {if (failed>0) {/* fprintf (stderr, "correcting failed by Signal\n "); */failed--; } return; } s=socket (Host,port); if (s<0) {failed++; continue;} if (Rlen!=write (S,req,rlen)) {failed++;close (s); continue;} if (http10==0) if (Shutdown (s,1)) {failed++;close (s); continue;} if (force==0) {/* read all available data from Socket */while (1) {if (timerexpired) Bre Ak I=read (s,buf,1500); /* fprintf (stderr, "%d\n", I); */if (i<0) {failed++; Close (s); Goto Nexttry; } else if (i==0) break; else bytes+=i; }} if (Close (s)) {failed++;continue;} speed++; }}
Random recording (webbench pressure test code)