webbench源码学习笔记

学习内容

  一共五百多行代码,其中包含了linux编程常用的API。可以通过学习源码,把不熟悉的API练习练习。

1 如何使用webbench

(1)查看参数帮助

 (2)运行方法

即以上模拟30个客户端在30秒期间并发请求百度,结果如下:

每分钟平均有1532次请求连接,服务器每秒传输字节为4039230,在30秒期间请求连接成功为766次,失败0次。

2 源码常用函数练习

(1) 选项参数

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

函数中的argc和argv通常直接从main()的两个参数传递而来。optsting是选项参数组成的字符串:

option结构数组,option结构称为长选项表,其声明如下:

 struct option 

      const char *name;               

      int has_arg;               

      int *flag;               

     int val;          

};  

结构中的元素解释如下: 

const char *name:选项名,前面没有短横线。譬如"help"、"verbose"之类。 

int has_arg:描述长选项是否有选项参数,如果有,是哪种类型的参数,其值见下表: 符号常量             数值            

含义 

no_argument            0            选项没有参数 

required_argument      1            选项需要参数 

optional_argument      2            选项参数是可选的

int *flag: 

如果该指针为NULL,那么getopt_long返回val字段的值; 

如果该指针不为NULL,那么会使得它所指向的结构填入val字段的值,同时getopt_long返回0 int val: 

如果flag是NULL,那么val通常是个字符常量,如果短选项和长选项一致,那么该字符就应该与optstring中

字符串optstring可以下列元素:

1.单个字符,表示选项,

2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。

3 单个字符后跟两个冒号,表示该选项后可以有参数也可以没有参数。如果有参数,参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。

optstring是一个字符串,表示可以接受的参数。例如,"a:b:cd",表示可以接受的参数是a,b,c,d,其中,a和b参数后面跟有更多的参数值。(例如:-a host --b name)

最后一个参数:longindex参数一般赋为NULL即可;如果没有设置为NULL,那么它就指向一个变量,这个变量会被赋值为寻找到的长选项在longopts中的索引值,这可以用于错误诊断。

函数使用方法:

  1  1 #include <getopt.h>
  2   2 
  3   3 #include <stdio.h>
  4   4 
  5   5 #include <stdlib.h>
  6   6 
  7   7 
  8   8 
  9   9 static  const   char    *program =NULL;
 10  10 
 11  11 
 12  12 
 13  13 static  const   struct  option long_opts[] = {
 14  14 
 15  15     {"help", no_argument, NULL, 'h'},
 16  16 
 17  17     {"version", no_argument, NULL, 'v'},
 18  18 
 19  19     {"author", required_argument, NULL, 'a'},
 20  20 
 21  21     {"date", no_argument, NULL, 'd'},
 22  22 
 23  23     {"time", no_argument, NULL, 't'},
 24  24 
 25  25     {0, 0, 0}
 26  26 
 27  27 };
 28  28 
 29  29 void    usage()
 30  30 
 31  31 {
 32  32 
 33  33     printf("argument: 
");
 34  34 
 35  35     printf("	 --version,-v 
"
 36  36 
 37  37               "	 --author, -a
"
 38  38 
 39  39               "	 --date, -d
"
 40  40 
 41  41               "	 --time, -t
"
 42  42 
 43  43               "	 --help,  -h
"
 44  44 
 45  45     );
 46  46 
 47  47 }
 48  48 
 49  49 
 50  50 
 51  51 int main(int argc,char* argv[])
 52  52 
 53  53 {
 54  54 
 55  55     char *str;
 56  56 
 57  57     int  long_index,c,ret;
 58  58 
 59  59     program = argv[0];
 60  60 
 61  61       while((c=getopt_long(argc, argv, "hva:dt", long_opts, &long_index))!=EOF){
 62  62 
 63  63           switch(c){
 64  64 
 65  65              case  'h':
 66  66 
 67  67                  usage();
 68  68 
 69  69                  exit(0);
 70  70 
 71  71              case  'v':
 72  72 
 73  73                  printf("version 1.2.0
");
 74  74 
 75  75                  break;
 76  76 
 77  77              case  'a':
 78  78 
 79  79          str=optarg;
 80  80 
 81  81                  printf("author is %s
",str);
 82  82 
 83  83                  break;
 84  84 
 85  85              case  'd':
 86  86 
 87  87                  printf("date is 2016.10.20
");
 88  88 
 89  89                  break;
 90  90 
 91  91              case  't':
 92  92 
 93  93                  printf("time is 12:30:45
");
 94  94 
 95  95                  break;
 96  96 
 97  97              default:
 98  98 
 99  99                  printf("ERR: please try: %s -h
", program);
100 100 
101 101                  exit(0);
102 102 
103 103           }
104 104 
105 105       }
106 106 
107 107       return 0;
108 108 
109 109 }
110 (2)字符串相关API
111 
112 strlen()//字符串长度
113 
114 bzero()//清空
115 
116 strstr()//子串查找
117 
118 strncpy()//复制
119 
120 strcat()//拼接
121 
122  1 #include <stdio.h>
123  2 #include <string.h>
124  3 #include <errno.h>
125  4 
126  5 int main(void)
127  6 {
128  7     char string[20];
129  8     char *str1="nihao";
130  9     strncpy(string,str1,3);
131 10     string[3]='';//字符串末尾0
132 11     printf("%s
",string);
133 12     //strcat(str1,str2)
134 13     char destnination[25];
135 14     char *blank="",*c="python",*borland="boland";
136 15     strcpy(destnination,borland);
137 16     strcat(destnination,blank);
138 17     strcat(destnination,c);
139 18     printf("%s
",destnination);
140 19 
141 20     //strncat(str1,str2,n)
142 21     char url[100]="http://www.baidu.com";
143 22     char path[20]="/cpp/string";
144 23     strncat(url,path,100);//100超过了path的长度
145 24     printf("%s
",url);
146 25     
147 26 
148 27     //strlen(str)
149 28     char str[5]="abcd";
150 29     printf("strlen(str)=%d,sizeof(str)=%d",strlen(str),sizeof(str));//4 5
151 30     
152 31     //strcmp 相等饭回0 str1大于str2 饭回正数
153 32     char *a="aBcDeE";
154 33     char *b="AbCdEf";
155 34     printf("strcmp(a,b):%d
",strcmp(a,b));
156 35 
157 36 
158 37     //strchr(str,c) 在str字符串中查找首次出现字符c的位置
159 38     char *s3="123445555656";
160 39     char *p5;
161 40     p5=strchr(s3,'5');
162 41 
163 42     printf("%ld
",s3);
164 43 
165 44     //strpbrk(str1,str2) 依次检验字符串str1的字符 当被检验字符在字符串str2中也包含的时候则停止检验 返回这个字符的位置
166 45     char *s1="see you again";
167 46     char *s2 = "you";
168 47     char *p=strpbrk(s1,s2);
169 48     if(p)
170 49     {
171 50         printf("the result is:%s
",p);
172 51     }else
173 52     {
174 53         printf("sorry
");
175 54     }
176 55     
177 56     //atoi(str) 字符串转换为int整数
178 57     //strstr 检索子串在字符串首次出现的位置
179 58     char *str5="hellodfdflhellop";
180 59     char *substr="hello";
181 60     char *s=strstr(str5,substr);
182 61     printf("%s
",s);
183 62 
184 63     //strerror 返回指向错误信息字符串的指针
185 64     char *buffer2=NULL;
186 65     buffer2=strerror(errno);
187 66     printf("Error:%s
",buffer2);
188 67     
189 68     //bzero(void *s,int n)
190 69     struct
191 70     {
192 71         int a;
193 72     char s[5];
194 73     float f;
195 74     }tt;
196 75     char ss[20];
197 76     bzero(&tt,sizeof(tt));
198 77     bzero(ss,20);//等价于memset(s,0,20)
199 78     return 0;
200 79 
201 80 
202 81 
203 82      
204 83 }
View Code

(3)信号相关API

案例https://www.cnblogs.com/yxk529188712/p/4983565.html

(4)IO相关

fwrite()

fread()

read()

(5)管道

int pipe(int fd[2]) 成功返回0,失败返回-1

管道和有名管道是进程间通信机制之一

管道是半双工,所以双方通信需要建立两个通道

FILE * fdopen(int fildes,const char * mode); 

fdopen取一个现存的文件描述符(我 们可能从 o p e n , d u p , d u p 2 , f c n t l或p i p e函数得到此文件描述符) ,并使一个标准的I / O流与该描述符相结合。此函数常用于由创建管道和网络通信通道函数获得的描述符。因为这些特殊类型的文件不能用标准I/O fopen函数打开,首先必须先调用设备专用函数以获得一个文件描述符,然后用f d o p e n使一个标准I / O流与该描述符相结合。   
fdopen()会将参数fildes 的文件描述符,转换为对应的文件指针后返回。参数mode 字符串   则代表着文件指针的流形态,此形态必须和原先文件描述词读写模式相同。

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 int main(int argc,char *argv[])
 6 {
 7     char buf[1024];
 8     int fds[2],fds2[2]; //fds[0]用于读  fds[1]用于写
 9     pipe(fds);
10     pipe(fds2);
11     if(fork()>0)//父亲进程
12     {
13         close(fds[1]);//读的时候应先关闭写
14         close(fds2[0]);   //写的时候先关闭读
15         while(memset(buf,0,1024),read(fds[0],buf,1024)>0)//从管道读
16         {
17             write(1,buf,strlen(buf));      //read是一个阻塞函数,会一直停在这里
18         }
19         close(fds[2]);   //要使用close关闭管道  管道也会堵塞
20  
21  
22         printf("father speaking:
");
23         FILE *fs=fdopen(fds2[1],"w");//管道与文件指针建立连接  可以不实用文件指针直接对管道操作
24         if(fs==NULL)                //while(memset(buf,0,1024),read(0,buf,1024)>0)
25         {                            //{     write(fds[1],buf,strlen(buf));}
26             perror("father died!
");
27         }
28         while(memset(buf,0,1024),fgets(buf,1024,stdin)!=NULL)//输入buf中
29         {
30             fprintf(fs,"father message:%s",buf);//写入文件
31             fflush(fs);
32         }
33         close(fds2[1]);        
34         wait(NULL);
35     }
36     else
37     {
38         close(fds[0]);
39         close(fds2[1]);//关闭写
40         FILE *fd=fdopen(fds[1],"w");//管道当作一个文件
41         if(fd==NULL)
42         {
43             perror("fdopen wrong
");
44         }
45         while(memset(buf,0,1024),fgets(buf,1024,stdin)!=NULL)
46         {
47             fprintf(fd,"child message:%s",buf);
48             fflush(fd);
49         }
50         close(fds[1]);
51  
52         while(memset(buf,0,1024),read(fds2[0],buf,1024)>0)
53         {
54             write(1,buf,strlen(buf));
55         }
56         close(fds2[0]);
57         exit(1);
58     }
59     return 0;
60 }
View Code

2 执行流程

 

 3 源码注释

  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 
 19 #include "socket.c"
 20 #include <unistd.h>
 21 #include <sys/param.h>
 22 #include <rpc/types.h>
 23 #include <getopt.h>
 24 #include <strings.h>
 25 #include <time.h>
 26 #include <signal.h>
 27 
 28 /* values */
 29 volatile int timerexpired=0;
 30 int speed=0;
 31 int failed=0;
 32 int bytes=0;
 33 
 34 /* globals */
 35 int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */
 36 /* Allow: GET, HEAD, OPTIONS, TRACE */
 37 #define METHOD_GET 0
 38 #define METHOD_HEAD 1
 39 #define METHOD_OPTIONS 2
 40 #define METHOD_TRACE 3
 41 #define PROGRAM_VERSION "1.5"
 42 int method=METHOD_GET;
 43 int clients=1;
 44 int force=0;
 45 int force_reload=0;
 46 int proxyport=80;
 47 char *proxyhost=NULL;
 48 int benchtime=30;
 49 
 50 /* internal */
 51 int mypipe[2];
 52 char host[MAXHOSTNAMELEN];
 53 #define REQUEST_SIZE 2048
 54 char request[REQUEST_SIZE];
 55 
 56 static const struct option long_options[]=
 57 {
 58     {"force",no_argument,&force,1},
 59     {"reload",no_argument,&force_reload,1},
 60     {"time",required_argument,NULL,'t'},
 61     {"help",no_argument,NULL,'?'},
 62     {"http09",no_argument,NULL,'9'},
 63     {"http10",no_argument,NULL,'1'},
 64     {"http11",no_argument,NULL,'2'},
 65     {"get",no_argument,&method,METHOD_GET},
 66     {"head",no_argument,&method,METHOD_HEAD},
 67     {"options",no_argument,&method,METHOD_OPTIONS},
 68     {"trace",no_argument,&method,METHOD_TRACE},
 69     {"version",no_argument,NULL,'V'},
 70     {"proxy",required_argument,NULL,'p'},
 71     {"clients",required_argument,NULL,'c'},
 72     {NULL,0,NULL,0}
 73 };
 74 
 75 /* prototypes */
 76 static void benchcore(const char* host,const int port, const char *request);
 77 static int bench(void);
 78 static void build_request(const char *url);
 79 
 80 static void alarm_handler(int signal)
 81 {
 82     timerexpired=1;
 83 }    
 84 
 85 static void usage(void)
 86 {
 87     fprintf(stderr,
 88             "webbench [option]... URL
"
 89             "  -f|--force               Don't wait for reply from server.
"
 90             "  -r|--reload              Send reload request - Pragma: no-cache.
"
 91             "  -t|--time <sec>          Run benchmark for <sec> seconds. Default 30.
"
 92             "  -p|--proxy <server:port> Use proxy server for request.
"
 93             "  -c|--clients <n>         Run <n> HTTP clients at once. Default one.
"
 94             "  -9|--http09              Use HTTP/0.9 style requests.
"
 95             "  -1|--http10              Use HTTP/1.0 protocol.
"
 96             "  -2|--http11              Use HTTP/1.1 protocol.
"
 97             "  --get                    Use GET request method.
"
 98             "  --head                   Use HEAD request method.
"
 99             "  --options                Use OPTIONS request method.
"
100             "  --trace                  Use TRACE request method.
"
101             "  -?|-h|--help             This information.
"
102             "  -V|--version             Display program version.
"
103            );
104 }
105 
106 int main(int argc, char *argv[])
107 {
108     int opt=0;
109     int options_index=0;
110     char *tmp=NULL;
111 
112     if(argc==1)
113     {
114         usage();
115         return 2;
116     } 
117 //getopt_long 参数处理 根据不同的选项对应不同的操作
118     while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF )
119     {
120         switch(opt)
121         {
122             case  0 : break;
123             case 'f': force=1;break;
124             case 'r': force_reload=1;break; 
125             case '9': http10=0;break;
126             case '1': http10=1;break;
127             case '2': http10=2;break;
128             case 'V': printf(PROGRAM_VERSION"
");exit(0);
129             case 't': benchtime=atoi(optarg);break;         
130             case 'p': 
131             /* proxy server parsing server:port */
132             tmp=strrchr(optarg,':');
133             proxyhost=optarg;
134             if(tmp==NULL)
135             {
136                 break;
137             }
138             if(tmp==optarg)
139             {
140                 fprintf(stderr,"Error in option --proxy %s: Missing hostname.
",optarg);
141                 return 2;
142             }
143             if(tmp==optarg+strlen(optarg)-1)
144             {
145                 fprintf(stderr,"Error in option --proxy %s Port number is missing.
",optarg);
146                 return 2;
147             }
148             *tmp='';
149             proxyport=atoi(tmp+1);break;
150             case ':':
151             case 'h':
152             case '?': usage();return 2;break;
153             case 'c': clients=atoi(optarg);break;
154         }
155     }
156 
157     if(optind==argc) {
158         fprintf(stderr,"webbench: Missing URL!
");
159         usage();
160         return 2;
161     }
162     //默认clients用户为1
163     if(clients==0) 
164         clients=1;
165     //默认压测30s
166     if(benchtime==0) 
167         benchtime=30;
168  
169     /* Copyright */
170     fprintf(stderr,"Webbench - Simple Web Benchmark "PROGRAM_VERSION"
"
171             "Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
"
172             );
173      //构造请求
174     build_request(argv[optind]);
175  
176     // print request info ,do it in function build_request
177     /*printf("Benchmarking: ");
178  
179     switch(method)
180     {
181         case METHOD_GET:
182         default:
183         printf("GET");break;
184         case METHOD_OPTIONS:
185         printf("OPTIONS");break;
186         case METHOD_HEAD:
187         printf("HEAD");break;
188         case METHOD_TRACE:
189         printf("TRACE");break;
190     }
191     
192     printf(" %s",argv[optind]);
193     
194     switch(http10)
195     {
196         case 0: printf(" (using HTTP/0.9)");break;
197         case 2: printf(" (using HTTP/1.1)");break;
198     }
199  
200     printf("
");
201     */
202 
203     printf("Runing info: ");
204 
205     if(clients==1) 
206         printf("1 client");
207     else
208         printf("%d clients",clients);
209 
210     printf(", running %d sec", benchtime);
211     
212     if(force) 
213         printf(", early socket close");
214     if(proxyhost!=NULL) 
215         printf(", via proxy server %s:%d",proxyhost,proxyport);
216     if(force_reload) 
217         printf(", forcing reload");
218     
219     printf(".
");
220     
221     return bench();
222 }
223 
224 //构造请求
225 void build_request(const char *url)
226 {
227     char tmp[10];
228     int i;
229 
230     //bzero(host,MAXHOSTNAMELEN);
231     //bzero(request,REQUEST_SIZE);
232     memset(host,0,MAXHOSTNAMELEN);
233     memset(request,0,REQUEST_SIZE);
234 
235     if(force_reload && proxyhost!=NULL && http10<1) 
236         http10=1;
237     if(method==METHOD_HEAD && http10<1)
238         http10=1;
239     if(method==METHOD_OPTIONS && http10<2)
240         http10=2;
241     if(method==METHOD_TRACE && http10<2)
242         http10=2;
243     //不同的构造头方法
244     /*
245     http头部格式
246     请求方法 空格 URL 空格 协议版本 

247     头部字段名    值    

248     

249     */
250     switch(method)
251     {
252         default:
253         case METHOD_GET: strcpy(request,"GET");break;
254         case METHOD_HEAD: strcpy(request,"HEAD");break;
255         case METHOD_OPTIONS: strcpy(request,"OPTIONS");break;
256         case METHOD_TRACE: strcpy(request,"TRACE");break;
257     }
258 
259     strcat(request," ");
260 
261     if(NULL==strstr(url,"://"))
262     {
263         fprintf(stderr, "
%s: is not a valid URL.
",url);
264         exit(2);
265     }
266     //url限制大小为1500
267     if(strlen(url)>1500)
268     {
269         fprintf(stderr,"URL is too long.
");
270         exit(2);
271     }
272     if (0!=strncasecmp("http://",url,7)) 
273     { 
274         fprintf(stderr,"
Only HTTP protocol is directly supported, set --proxy for others.
");
275         exit(2);
276     }
277     
278     /* protocol/host delimiter */
279     i=strstr(url,"://")-url+3;
280 
281     if(strchr(url+i,'/')==NULL) {
282         fprintf(stderr,"
Invalid URL syntax - hostname don't ends with '/'.
");
283         exit(2);
284     }
285     
286     if(proxyhost==NULL)
287     {
288         /* get port from hostname */
289         if(index(url+i,':')!=NULL && index(url+i,':')<index(url+i,'/'))
290         {
291             strncpy(host,url+i,strchr(url+i,':')-url-i);
292             //bzero(tmp,10);
293             memset(tmp,0,10);
294             strncpy(tmp,index(url+i,':')+1,strchr(url+i,'/')-index(url+i,':')-1);
295             /* printf("tmp=%s
",tmp); */
296             proxyport=atoi(tmp);
297             if(proxyport==0) proxyport=80;
298         } 
299         else
300         {
301             strncpy(host,url+i,strcspn(url+i,"/"));
302         }
303         // printf("Host=%s
",host);
304         strcat(request+strlen(request),url+i+strcspn(url+i,"/"));
305     } 
306     else
307     {
308         // printf("ProxyHost=%s
ProxyPort=%d
",proxyhost,proxyport);
309         strcat(request,url);
310     }
311 
312     if(http10==1)
313         strcat(request," HTTP/1.0");
314     else if (http10==2)
315         strcat(request," HTTP/1.1");
316   
317     strcat(request,"
");
318       //到这里头部构造完成
319       
320     if(http10>0)
321         strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"
");
322     if(proxyhost==NULL && http10>0)
323     {
324         strcat(request,"Host: ");
325         strcat(request,host);
326         strcat(request,"
");
327     }
328  
329     if(force_reload && proxyhost!=NULL)
330     {
331         strcat(request,"Pragma: no-cache
");
332     }
333   
334     if(http10>1)
335         strcat(request,"Connection: close
");
336     
337     /* add empty line at end */
338     if(http10>0) 
339         strcat(request,"
"); 
340     
341     printf("
Request:
%s
",request);
342 }
343 
344 /* vraci system rc error kod */
345 static int bench(void)
346 {
347     int i,j,k;    
348     pid_t pid=0;
349     FILE *f;
350 
351     /* check avaibility of target server */
352     i=Socket(proxyhost==NULL?host:proxyhost,proxyport);
353     if(i<0) { 
354         fprintf(stderr,"
Connect to server failed. Aborting benchmark.
");
355         return 1;
356     }
357     close(i);
358     
359     /* 创建管道 */
360     if(pipe(mypipe))
361     {
362         perror("pipe failed.");
363         return 3;
364     }
365 
366     /* not needed, since we have alarm() in childrens */
367     /* wait 4 next system clock tick */
368     /*
369     cas=time(NULL);
370     while(time(NULL)==cas)
371     sched_yield();
372     */
373 
374     /* fork childs */
375     //多少个用户多少个进程 fork一次返回两个
376     for(i=0;i<clients;i++)
377     {
378         pid=fork();
379         if(pid <= (pid_t) 0)
380         {
381             /* child process or error*/
382             sleep(1); /* make childs faster */
383             break;
384         }
385     }
386 
387     if( pid < (pid_t) 0)
388     {
389         fprintf(stderr,"problems forking worker no. %d
",i);
390         perror("fork failed.");
391         return 3;
392     }
393     //如果是子进程
394 
395     if(pid == (pid_t) 0)
396     {
397         /* I am a child */
398         if(proxyhost==NULL)
399             benchcore(host,proxyport,request);
400         else
401             benchcore(proxyhost,proxyport,request);
402 
403         /* write results to pipe */
404         //构造完请求得到结果写入管道
405         f=fdopen(mypipe[1],"w");
406         if(f==NULL)
407         {
408             perror("open pipe for writing failed.");
409             return 3;
410         }
411         /* fprintf(stderr,"Child - %d %d
",speed,failed); */
412         fprintf(f,"%d %d %d
",speed,failed,bytes);
413         fclose(f);
414 
415         return 0;
416     } 
417     else
418     {
419         //父进程从管道读数据
420         f=fdopen(mypipe[0],"r");
421         if(f==NULL) 
422         {
423             perror("open pipe for reading failed.");
424             return 3;
425         }
426         
427         setvbuf(f,NULL,_IONBF,0);//不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略
428         
429         speed=0;
430         failed=0;
431         bytes=0;
432     
433         while(1)
434         {
435             pid=fscanf(f,"%d %d %d",&i,&j,&k);
436             if(pid<2)
437             {
438                 fprintf(stderr,"Some of our childrens died.
");
439                 break;
440             }
441             
442             speed+=i;
443             failed+=j;
444             bytes+=k;
445         
446             /* fprintf(stderr,"*Knock* %d %d read=%d
",speed,failed,pid); */
447             if(--clients==0) 
448                 break;
449         }
450     
451         fclose(f);
452 
453         printf("
Speed=%d pages/min, %d bytes/sec.
Requests: %d susceed, %d failed.
",
454             (int)((speed+failed)/(benchtime/60.0f)),
455             (int)(bytes/(float)benchtime),
456             speed,
457             failed);
458     }
459     
460     return i;
461 }
462 
463 void benchcore(const char *host,const int port,const char *req)
464 {
465     int rlen;
466     char buf[1500];
467     int s,i;
468     struct sigaction sa;
469 
470     /* setup alarm signal handler */
471     sa.sa_handler=alarm_handler;
472     sa.sa_flags=0;
473     if(sigaction(SIGALRM,&sa,NULL))
474         exit(3);
475     
476     alarm(benchtime); // after benchtime,then exit
477 
478     rlen=strlen(req);
479     nexttry:while(1)
480     {
481         if(timerexpired)
482         {
483             if(failed>0)
484             {
485                 /* fprintf(stderr,"Correcting failed by signal
"); */
486                 failed--;
487             }
488             return;
489         }
490         
491         s=Socket(host,port); //尝试连接
492         //失败次数统计
493         if(s<0) 
494         {
495             failed++;
496             continue;
497         } 
498         
499         if(rlen!=write(s,req,rlen)) 
500         {
501             failed++;
502             close(s);
503             continue;
504         }
505         if(http10==0) 
506         if(shutdown(s,1)) 
507         {
508             failed++;
509             close(s);
510             continue;
511         }
512         if(force==0) 
513         {
514             /* read all available data from socket */
515             while(1)
516             {
517                 if(timerexpired) break; 
518                 i=read(s,buf,1500);
519                 /* fprintf(stderr,"%d
",i); */
520                 if(i<0) 
521                 { 
522                     failed++;
523                     close(s);
524                     goto nexttry;
525                 }
526                 else
527                 if(i==0) 
528                     break;
529                 else
530                     bytes+=i;//read返回的是字节数 所以在此可以统计字节数
531             }
532         }
533         if(close(s)) 
534         {
535             failed++;
536             continue;
537         }
538         speed++;
539     }
540 }
View Code
原文地址:https://www.cnblogs.com/lanjianhappy/p/11855636.html