First, the program description: This program tests the performance of the above PNG server. (Developed in FreeBSD, and compile the Windows Cygwin environment).
Second, the instructions: (similar to ab) st [options] [http: //] hostname / path -n requests number of requireds to perform -c concurrency number of multiple requests to make -v print version number and exit -h display Usage information (this message) Third, source code: / *********************************************** *************************************** * CopyRight (c) 2004-2005 Xiongbin Xiong All Rights Reserved * References: Stevens, WR 1992. Advanced Programming In The Unix Environment. * Addison-Wesley. * Stevens, WR 1998. UNIX Network Programming Volum1. * Prentice Hall Ptr. * /
#include
#define buffsize 65535 # Define maxline 4096
Static int requests = 1; / * The number of requests executed in the test session, the default is a * / static int concurrency = 1; / * concurrency level, once the number of requests, the default is one * / static int tent DONE; / * Number of requests completed in the test session * / static int recvdata = 0; / * received total data * / static char * hostname, * pathname; / * Host name, request path name * / static Struct TimeVal Take_time; / * Complete the time required to complete all requests * / static int lflag; / * child process end count flag * /
INT PARSE_URL (Char *); / * Decompose URL to HostName and Pathname * / Int Test (Void); / * Start Test * / Int Con_Test (int); / * concurrent process test * / int fork_do (void); / * Test program * / int record (int); / * Record test data * / int Lock_reg (int, int, int, OFF_T, INT, OFF_T); / * Use record lock to protect the shared file * / static void Output_Results (void); / * Output result * / static void sig_chld (int); / * Processing sub-process SIGCHLD signal * / static void usage (const char *); / * Tip information * / static void err (char *); / * Error handler * / static void copyright (void); / * version information * / INTMAIN (int Argc, char * argv []) {int flag; char * url; file * fp; if (argc <2 || argc > 6) {Printf ("Invalid INPUT / N"); USAGE (Argv [0]); exit (1);}
OpterR = 0; while ((Flag = getopt (argc, argv, "n: c: hv")))! = EOF) {switch (flag) {copy 'n': requests = atoi (OPTARG); / * Total request Number * / if ("INVALID NUMBER of Requests"); Break; Case 'C': Concurrency = ATOI (OPTARG); / * Concurrently requested level, that is, each concurrent request Number of requests * / if ("Invalid Number of Concurrency"; Break; Case 'h': usage (argv [0]); / * Help information * / Break; Case 'V': CopyRight (); / * Version information * / exit (0); case '?': Printf ("Unrecognized Option: -% C / N", Optopt); / * Error Parameters * / usage (Argv [0]); EXIT (1);}}} IF (Requests IF (Opt> = Argc) Err ("Invalid INPUT"); Else URL = Argv [Optind]; IF (PARSE_URL (URL)) / * Decomposes URL to Hostname and Pathname * / Err ("Invalid Url Address"); Copyright (); Write (stdout_fileno, "testing ...", 10); Test (); / * Start test * / output_results (); / * result output * / unlink ("temp.log"); / * Delete temporary file * / exit (0);} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------- * // * Decompose URL to Hostname and Pathname * / INTPARSE_URL (Char * URL) {char * p, * pp, * urlptr; URLPTR = URL; IF (strncmp (urlptr, "http: //", 7) == 0) / * Looking for "http: //" * / urlptr = urlptr 7; if ((p = strstr (URLPTR) "/ n"))! = 0) / * Looking for "/ n" * / * p = '/ 0'; p = strchr (urlptr, '/'); / * Looking for '/' * / if ( P == 0) Return (1); PathName = P 1; / * Get pathname * / * p = '/ 0'; hostname = urlptr; / * Get hostname * / return (0);} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------- * // * Start test * / inttest (void) {INT I, N, M; Struct TimeVal Start_time, End_Time; n = Requests / ConcURRENCY; / * N is the number of concurrent cycles * / m = requests% concurrency; / * When the top cannot be completely removed, M is the last concurrent request concurrent level * / GetTimeOfDay (& Start_time, NULL); / * Get test start time * / for (i = 0; i if (end_time.tv_usec Return;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------- * // * Concurrent Process Test * / INTCON_TEST (INT Level) {INT I, PID; LFLAG = level; sign (sigchld, sig_chld); / * Get sigchld signal * / for (i = 0; i INT i, N, L, K, PID, PPID; Struct Sockaddr_in servaddr; char buf [buffsize], pngname [maxline], cpid [8], * p, * h, rbuf [maxline] = "get /"; * ffp; int suckfd; struct hostent * hp; struct in_addr ** ptr; hp = gethostbyname (hostname); / * Get IP address * / PTR = (struct in_addr **) hp-> h_addr_list; sockfd = socket (AF_INET, SOCK_STREAM, 0); bzero (& servaddr, sizeof (servaddr)); / * initialize the socket address structure * / servaddr.sin_family = AF_INET; servaddr.sin_port = htons (80); memcpy (& servaddr.sin_addr , * PTR, SIZEOF (STRUCT IN_ADDR)); L = 0; IF (Connect (SockFD, Steruct SockAddr *) & Servaddr, SIZEOF (Servaddr)) <0) Printf ("Connect Error / N"); Else {/ * Connection Success * / STRCAT (RBUF, Pathname); STRCAT (RBUF, "Http / 1.0"); / * Form a GET request command * / n = Strlen (RBUF); IF (Write (SOCKFD, RBUF, N)! = n) / * Send GET Request to Server * / Err ("Fork_DO (): Write Error"); L = Recv (Sockfd, BUF, SizeOf (BUF), 0); / * Receive server return data * / IF ((pID = getPID ()) <0) Err ("" fork_do (): getpid error "); Sprintf (CPID,"% D ", PID); STRCPY (pngname, "clipng"); strcat (pngname, cpid); strcat (pngname, ""); / * File name with PID * / FFP = FOPEN (PNGName, "WB"); / * Create a file * / unlink (pngname); P = strstr (buf, "/ n / n"); h = buf; k = p-h 2; / * Positioning in the PNG data area begins * / fwrite (& BUF [K], Sizeof (char), LK , FFP); / * Write data * /} Record (L); / * Record the data of this request * / close (sockfd); fclose (ffp); return (0);} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------- * // * Record the test data * / intRecord (int RECVN) {INT FD, A, B; File * FP; IF ((FP = FOPEN ("Temp.log", "R ")) == NULL) / * Read and write mode open file * / return (1); fd = fileno (fp); While (Lock_reg (fd, f_setlk, f_wrlck, 0, seek_set, 0)) == - 1); / * to lock the file * / fscanf (FP, "% D / T% D", & A, & B); / * Current data from the file * / if (recvn) B = Recvn; / * If the connection is successful, the data is received * / else A-; / * Connect failed, the number of completed is 1 * / rebind (fp); FPRINTF (FP, "% D / T% D", A, B); / * Write file * / lock_reg (fd, f_setlk, f_unlck, 0, seek_set, 0); / * Unlock * / Fclose (fp); Return (0); / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------- * // * Use the record lock to protect the shared file * / Intlock_reg (int FD, INT CMD, Int type, off_t offset, int ime, OFF_T LEN) {struct flock lock; Lock.l_type = type; / * f_rdlck, f_wrlck, f_unlck * / lock.l_start = offset; / * Byte Offset, the relative offset of the start space * / lock.l_whence = because; / * seek_set, seek_cur, seek_end * / LOCK.L_LEN = LEN; / * The length of the area (0 is indicated to the maximum location) * / Return (FCNTL (FD, CMD, & Lock); / * Using record lock * /} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------- * // * Output result * / static voidoutput_results (void) {float takentime; file * fp; FP = FOPEN ("Temp.log", "R"); FSCANF (FP, "% D / T% D", & DONE, & Recvdata); / * Get data from the file * / takentime = ((float) Take_time. TV_SEC) (FLOAT) Take_time.tv_usec) / 1000000.0F; / * Format is an integer decimal form * / Printf ("/ n / n"); Printf ("Server Hostname:% S / N", HostName); / * Hostname * / Printf ("Server Port:% HD / N", 80); / * Port * / Printf ("Document Path: /% S / N", PathName); / * Request the path name * / printf ("/ n"); Printf ("Total Requests:% D / N", requests; / * Request Number * / printf ("Concurrency Level:% D / N", Concurrency); / * concurrent * / printf ("Time Taken For Tests:% LD.% 03LD Seconds / N", Take_Time.tv_Sec, Take_Time.tv_usec) ; / * Total time consumption * / printf ("" "Complete Requests:% LD / N", DONE); / * Complete the number of requests * / Printf ("Failed Requests:% LD / N", (Requests-Done); / * Fail request number * / printf ("Total TransferRed:% ld bytes / n", recvdata); / * Total data volume * / printf ("/ n"); if (takentime) {Printf ("Requests per second: % .2F [# / sec] / n "/ n", (float)); / * Complete a number of requests per second * / printf ("Time Per Request:% .3F [MS] (mean) / n ", (float) (1000 * concurrency * takentime / done)); / * Complete a concurrent request time * / printf (" Time Per Request:% .3F [MS] (Mean, Across All Concurrent Requests) / n ", (float) (1000 * takentime / done); / * Complete a request time * / printf (" Transfer rate: % .2f [kbytes / sec] received / n ", (float) (RecvdataS / Takentime / 1024)); / * Transfer data volume per second * /} printf (" / n ");} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------- * // * Processing sub-process sigchld signal * / static voidsig_chld (int sign) {PID_T PID; int Stat; While (PID = WaitPID (-1, & stat, 1))> 0) / * Processes the end child process status, prevent the child process Zombie status * / LFLAG -; / * Sign minus one * / Return;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------- * // * Tips Information * / static voidusage (const char * propename) {fprintf (stderr, "usage:% s [options] [http://] hostname / path / n ", progName); FPRINTF (stderr," options are: / n "); fprintf (stderr," -n requests number of requests to perform / n "); FPRINTF (stderr , "-C concurrency number of multiple requests to make / n"); fprintf (stderr, "-v print version number and exit / n"); FPrintf (stderr, "-h display usage information (this message) / n" ); Exit (0);} / * -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------- * // * error handage function * / static voiderr (char * s) {fprintf (stderr , "% s / n", s); exit (1);} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------- * // * Version information * / static voidcopyright (void) {printf ("this is servertest for my pngserver, version 1.0 / n "); Printf (" CopyRight (C) 2004-2005 Xiongbin Xiong All Rights Reserved / N "); Printf (" hustxxb@hotmail.com/n "); Printf (" / n ");} / * END All * /