zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    kingbase8d常见问题
    kibana-7.9.1安装
    ElasticSearch-7.9.1
    在线分析-jstack
    Wireshark常用过滤条件
    shiro登录认证过程
    查看mysql库中所有表的大小和记录数
    linux设置定时任务crontab
    POI 使用常见问题
    Java源码之String-构造方法
  • 原文地址:https://www.cnblogs.com/lanjianhappy/p/11855636.html
Copyright © 2011-2022 走看看