Webbench Source analysis of the 10 most noteworthy C open source projects

Source: Internet
Author: User
Tags cas signal handler

Webbench

Webbench is a very simple web site pressure measurement tool that is used under Linux. It uses fork () to simulate multiple clients accessing the URL we set at the same time, testing the performance of the site under pressure, and simulating up to 30,000 concurrent connections to test the load capacity of the site. Webbench use C language, code is too concise, the source add up to less than 600 lines.

Webbench commands for pressure measurement:

Webbench-c 300-t URL

Where:-C 300 represents the number of concurrent (can be understood as a client),

-T 10 indicates time (seconds)

URL to be measured by URL

Download Link: http://home.tiscali.cz/~cz210552/webbench.html


The flowchart for the entire code is as follows:



First, we start from the main function, the front several are initialized variables, nothing to say, there is a getopt_long function, there should be some people have not used this function, I first to analyze the function bar ~

int Getopt_long (int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);

1, the first two parameters, is the main function of ARGC and argv, which can be directly passed in,
2, optstring format examples are convenient, for example: char *optstring = "ABCD:";
After this optstring is passed in, the Getopt function checks to see if the command line specifies the-a,-B,-C, and-D, which requires multiple calls to the GETOPT function until it returns 1, and when it is checked that one of the above parameters is specified, The function returns the specified parameter name (that is, the letter), followed by a colon after the last parameter D: indicates that parameter D can specify a value, such as-D 100 or-D user.

3, Longopts points to an array of option structures, each element of that array, indicating the name and nature of a "long parameter" (that is, a parameter of the form--name):
struct Option {
const char *name;
int has_arg;
int *flag;
int Val;
};

Names is the name of the parameter
Has_arg indicates whether a parameter value is available, and its value is optional:
No_argument (i.e. 0) indicates that the long parameter is not with a parameter (i.e. without a value, such as:--name)
Required_argument (i.e., 1) indicates that the long parameter must be with a parameter (i.e. must have a value, such as:--name Bob)
Optional_argument (that is, 2) indicates that the parameters behind the long parameter are optional (that is, both--name and--name Bob Can)

Flag when this pointer is empty, the function returns the value of Val directly from the return value of the Getopt_long, and when it is not empty, Val is assigned to the integer number pointed to by the flag, and the return value of the function is 0.

Val is used to specify the return value when the function finds the option, or to specify the value of the data that flag points to when flag is not empty.

static const struct Option long_options[]={{"force", no_argument,&force,1}, {"Reload", No_argument,&force_ reload,1}, {"Time", Required_argument,null, ' t '},//bench test times default to 30s {"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}};
4, the variable that the Option_index points to will record the description of the element that is currently found in accordance with longopts, which is the subscript value of the longopts.

For example for

while (opt = Getopt_long (argc, argv, optstring, Long_options, &option_index))! =-1)     {          printf ("opt =%c\n", opt);           The specified parameter name (that is, the letter)        printf ("Optarg =%s\n", optarg);     Optarg the specified value for the parameter        printf ("Optind =%d\n", optind);          The next subscript value in the argv that will be processed to the parameter.        printf ("argv[optind-1] =%s\n",  argv[optind-1]);          printf ("Option_index =%d\n", option_index);          The variable it points to will record the description of the element that is currently found in accordance with longopts, which is the subscript value of the longopts.   }  


Enter command line Test_getopt_long-reqarg 100

Output:
opt = Reqarg
Optarg = 100
Optind = 3
ARGV[OPTIND-1] = 100


Second, build_request function
The purpose is to process the URL and get host,proxyport,request
Where request is the message to be sent after the socket is used to communicate with host.

void Build_request (const char *url) {char tmp[10];  int i;    Bzero (Host,maxhostnamelen);  The Maxhostnamelen byte is zero before the host string and includes '. '  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 forOthers.\n ");           Exit (2);          }/* Protocol/host delimiter */i=strstr (URL, "://")-url+3; Locate the URL://The occurrence of the location/* printf ("%d\n", I); */if (STRCHR (url+i, '/') ==null) {//To determine if there is a '/' fprintf (stderr, "\ninvalid url sy) After the URL is removed/http                                Ntax-hostname don ' t ends with '/'. \ n ');                              Exit (2); } if (Proxyhost==null)//if in order to get the port number hostname and request {//For example url= "Http://localhost:12345/test";//if after the run is over proxyport= 12345,host=localhost/* Get port from hostname */if (index (Url+i, ': ')!=null && index (url+i, ': ') <index (        Url+i, '/')) {strncpy (HOST,URL+I,STRCHR (url+i, ': ')-url-i);   Char *strncpy (char *destin, char *source, int//maxlen), copies the first n bytes of a string that is referred to as the null end of SRC to the array referred to by Dest.   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);}


Three, bench function
This function mainly uses the fork-out subprocess to test the Web site, and uses the main process to read all the data written by the child processes, each child process calls the Benchcore function to test to the global variable speed faulted,
Finally, the main process summarizes the data of each child thread to show ~

/* 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); Test whether the Web site can connect 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 ();      1) In the parent process, fork returns the process ID of the newly created child process;  2) in the sub-process, fork returns 0;   3) If an error occurs, fork returns a negative value;   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);         Bench's core code sub-process enters this function to test the Web site until Benchtime is consumed by the 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);//each sub-process writes the test results to the pipe 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); Setvbuf is to set the buffer configuration of the file stream, such as setvbuf (input, BUFR, _IOFBF, 512) is set input this file stream uses BUFR//refers to the 512 bytes as the input file buffer, when you manipulate in  Put file, the data will be temporarily present BUFR//inside, each time you read input, the system will read 512 bytes to the BUFR.          Speed=0;          Failed=0;  bytes=0; while (1) {pid=fscanf (F, "%d%d", &i,&j,&k), the main process reads the data written by each sub-process from the pipe and reads it into the i,j,k respectively, because the pipe is blocked when empty, if (PID &LT;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;  When the results of all child process writes have been read, the process ends} 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); Outputs the result of all child processes recording the sum of data} return i;


Four, Benchcore function
This function mainly uses the socket connection, sends request, receives to test the website, the test result exists the global variable speed faulted,bytes
Exit function at end of timed time ~

Where to use the Sigaction function:
int sigaction (int signo,const struct sigaction *restrict act,struct sigaction *restrict oact);
One of the Signo information can be consulted: http://blog.csdn.net/liucimin/article/details/40507443

The structure of sigaction is defined as follows:

struct sigaction{  void (*sa_handler) (int);   sigset_t Sa_mask;  int Sa_flag;  

The Sa_handler field contains the address of a signal capture function
Sa_flag logo.

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 *//Set timer, the process benchtime end test Sa.sa_handler=alarm_handl Er sa.sa_flags=0; if (Sigaction (sigalrm,&sa,null))//sets the value of the global variable timerexpired after the time of the signal exit (3); Alarm (benchtime);//alarm is also known as the alarm clock function, which can set a timer in the process, and when the timer specifies the time to//, it sends a SIGALRM signal to the process. If this signal is ignored or not captured//, its default action is to terminate the process that invokes the alarm function. Rlen=strlen (req); Nexttry:while (1) {if (timerexpired)//To End Function {if (failed>0) {/* fprintf (stderr, "correcting Failed by signal\n ");       */failed--;    } return;                          } s=socket (Host,port);     The socket is a function written by itself in the header file, returning the result of the socket connection if (s<0) {failed++;continue;}       if (Rlen!=write (S,req,rlen)) {failed++;close (s); continue;}    Send request to server if (http10==0) if (Shutdown (s,1)) {failed++;close (s); continue;} if (force==0) {/* REAd all available data from Socket */while (1) {if (timerexpired) break;                       I=read (s,buf,1500); The number of bytes read successfully returned, error 1 and set errno, if the end of the file was reached before the read, the read returned 0/* fprintf (stderr, "%d\n", I);                 */if (i<0)//Read failed failed++, resend request read data {failed++;                 Close (s);              Goto Nexttry;                } else if (i==0) break;    else bytes+=i;    }} if (Close (s)) {failed++;continue;} speed++; }}



Webbench Source analysis of the 10 most noteworthy C open source projects

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.