/****************************************************************************
*
* webbench-1.5_hacking
*
* 1.这是webbench-1.5版本中webbench.c(主程序)的源码,源码不到700行(除去注释).
* 2.通过分析、阅读该源码,可以一窥浏览器访问服务器的原理以及web服务器
* 压力测试的原理.
* 3.知识量:
* 1.C语言;
* 2.Unix或类Unix系统编程;
* 3.微量的http协议(请求行、消息头、实体内容);
* 4.如何阅读别人的代码( 从main函数开始 :) );
* 4.webbench-1.5 文件结构如下:
* .
* |-- COPYRIGHT -> debian/copyright
* |-- ChangeLog -> debian/changelog
* |-- Makefile -------->makefile 文件
* |-- debian
* | |-- changelog
* | |-- control
* | |-- copyright
* | |-- dirs
* | `-- rules
* |-- socket.c -------->里面定义了Socket()函数供webbench.c调用
* |-- webbench.1 -------->说明文档,使用shell命令查看: less webbench.1
* `-- webbench.c -------->你接下来要阅读的文件
*
* 5.如何阅读该文档:
* 1.linux下使用vi/vim配和ctags,windows下使用Source Insight,当然你也
* 可以用其他文本编辑器看.
* 2.先找到main函数,然后就可以开始阅读了,遇到对应的函数,就去看对应的
* 函数.
* 3.对于有些函数,本人没有添加注释,或者说本人觉得没必要.
* 4.祝您好运. :)
*
* 6.webbench-1.5版本下载url: http://home.tiscali.cz/~cz210552/webbench.html
*
* 如果您对本文有任何意见、提议,可以发邮件至zengjf42@163.com,会尽快回复.
* 本文的最终解释权归本人(曾剑锋)所有,仅供学习、讨论.
*
* 2015-3-24 阴 深圳 尚观 Var
*
***************************************************************************/ /*
* (C) Radim Kolar 1997-2004
* This is free software, see GNU Public License version 2 for
* details.
*
* Simple forking WWW Server benchmark:
*
* Usage:
* webbench --help
*
* Return codes:
* 0 - sucess
* 1 - benchmark failed (server is not on-line)
* 2 - bad param
* 3 - internal error, fork failed
*
*/ #include "socket.c"
/**
* 以下是socket.c中的主要代码:
*
* //
* // Socket函数完成的工作:
* // 1. 转换IP,域名,填充struct sockaddr_in,获取对应的socket描述符;
* // 2. 连接服务器;
* //
*
* int Socket(const char *host, int clientPort)
* {
* //
* // 局部变量说明:
* // 1. sock : 用来保存要返回的socket文件描述符;
* // 2. inaddr : 保存转换为网络序列的二进制数据;
* // 3. ad : 保存连接网络服务器的地址,端口等信息;
* // 4. hp : 指向通过gethostbyname()获取的服务器信息;
* //
*
* int sock;
* unsigned long inaddr;
* struct sockaddr_in ad;
* struct hostent *hp;
*
* memset(&ad, 0, sizeof(ad));
* ad.sin_family = AF_INET;
*
* //
* // 这一段主要完成以下功能:
* // 1. 如果传入的是点分十进制的IP,那么直接转换得到网络字节序列IP;
* // 2. 如果传入的域名,这需要是用gethostbyname()解析域名获取主机IP;
* //
* inaddr = inet_addr(host); //将点分十进制IP转换成网络序列的二进制数据
* //如果host不是点分十进制的,那么返回INADDR_NONE
* 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);
*
* //
* // 这一段主要完成的工作:
* // 1. 获取socket;
* // 2. 连接网络服务器;
* //
* 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=; //定时器定时到了的标志,子进程根据这个标志退出
int speed=; //正常响应请求数
int failed=; //不正常响应请求数
int bytes=; //从服务器接收返回的数据字节数 /* globals */
/**
* 支持的网络协议,默认是: http/1.0
* 1. 0 - http/0.9
* 2. 1 - http/1.0
* 3. 2 - http/1.1
*/
int http10=; /* Allow: GET, HEAD, OPTIONS, TRACE */
#define METHOD_GET 0
#define METHOD_HEAD 1
#define METHOD_OPTIONS 2
#define METHOD_TRACE 3
#define PROGRAM_VERSION "1.5"
int method = METHOD_GET; //默认请求方式get int clients = ; //默认的客户端数量
int force = ; //连接访问web后是否接收服务器返回的数据
int force_reload = ; //是否让浏览器缓存页面
int proxyport = ; //默认代理端口
char *proxyhost = NULL; //代理主机域名
/**
* 默认的测试时间:30s,主要是给子进程的闹钟,时间到了timerexpired会置1,
* 子进程会根据这个条件退出循环,并通过管道给父进程发送benchtime对应的
* 时间内对服务器访问的数据:speed,failed,bytes.
*/
int benchtime = ; /* internal */
/**
* 父进程与子进程通信通过管道进行通信:
* 1. mypipe[0] : 是读的管道端口;
* 2. mypipe[1] : 是写的管道端口;
*/
int mypipe[];
/**
* 存放点分十进制字符串或者域名
*/
char host[MAXHOSTNAMELEN];
/*
* 保存http协议请求头,主要是在build_request()中完成相关操作;
*/
#define REQUEST_SIZE 2048
char request[REQUEST_SIZE]; /**
* struct option是getopt.h中定义的结构体:
*
* struct option
* {
* const char *name; //表示长参数名
*
* //
* // # define no_argument 0 //表示该参数后面没有参数
* // # define required_argument 1 //表示该参数后面一定要跟个参数
* // # define optional_argument 2 //表示该参数后面可以跟,也可以不跟参数值
* //
* int has_arg;
*
* //
* // 用来决定,getopt_long()的返回值到底是什么:
* // 1. 如果flag是NULL(通常情况),则函数会返回与该项option匹配的val值;
* // 2. 如果flag不是NULL,则将val值赋予flag所指向的内存,并且返回值设置为0;
* //
* int *flag;
* int val; //和flag联合决定返回值
* };
*/
static const struct option long_options[]=
{
{"force",no_argument,&force,},
{"reload",no_argument,&force_reload,},
{"time",required_argument,NULL,'t'},
{"help",no_argument,NULL,'?'},
{"http09",no_argument,NULL,''},
{"http10",no_argument,NULL,''},
{"http11",no_argument,NULL,''},
{"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,,NULL,}
}; /* prototypes */
static void benchcore(const char* host,const int port, const char *request);
static int bench(void);
static void build_request(const char *url); /**
* alarm_handler函数功能:
* 1. 闹钟信号处理函数,当时间到了的时候,timerexpired被置1,表示时间到了;
* 2. benchcore()中会根据timerexpired值来判断子进程的运行;
*
*/
static void alarm_handler(int signal)
{
timerexpired=;
} /**
* usage函数功能:
* 输出webbench的基本是用方法.
*/
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 protocol.\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"
);
}; /**
* main函数完成功能:
* 1. 解析命令行参数;
* 2. 组合http请求头;
* 3. 打印一些初步解析出来的基本信息,用于查看对比信息;
* 4. 调用bench创建子进程去访问服务器;
*/
int main(int argc, char *argv[])
{
/**
* 局部变量说明:
* 1. opt : 返回的操作符;
* 2. options_index : 当前解析到的长命令行参数的下标;
* 3. tmp : 指向字符的指针;
*/
int opt=;
int options_index=;
char *tmp=NULL; if(argc==)
{
usage();
return ;
} while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF )
{
switch(opt)
{
case : break;
case 'f': force=;break; //不接收服务器返回的数据
case 'r': force_reload=;break; //不缓存请求数据,目前不知有何用
case '': http10=;break; //选择http/0.9
case '': http10=;break; //选择http/1.0
case '': http10=;break; //选择http/1.1
case 'V': printf(PROGRAM_VERSION"\n");exit(); //返回webbench版本号
case 't': benchtime=atoi(optarg);break; //设置基准测试时间
case 'p':
/* proxy server parsing server:port */
/**
* 传入的参数格式:<IP:port>或者<域名:port>,可能的错误有以下3种可能:
* 1. 传入的参数没有是用:分开IP(或域名)和端口号,包括了没有传参数;
* 2. 使用了':'号,但是没有给出IP;
* 3. 使用了':'号,但是没有给出端口号;
*/
tmp=strrchr(optarg,':');
proxyhost=optarg;
if(tmp==NULL)
{
break;
}
if(tmp==optarg)
{
fprintf(stderr,"Error in option --proxy %s: Missing hostname.\n",optarg);
return ;
}
if(tmp==optarg+strlen(optarg)-)
{
fprintf(stderr,"Error in option --proxy %s Port number is missing.\n",optarg);
return ;
}
/**
* 将':'换成'\0',这样就得到了IP(或域名)字符串和port字符串,并通过atoi()获取端口号
*/
*tmp='\0';
proxyport=atoi(tmp+);break;
case ':':
case 'h':
case '?': usage();return ;break;
case 'c': clients=atoi(optarg);break; //指定要生成多少个客户端,默认是1个
}
} /**
* 命令行参数没有给出URL
*/
if(optind==argc) {
fprintf(stderr,"webbench: Missing URL!\n");
usage();
return ;
} /**
* 修正客户端数量和运行时间
*/
if(clients==) clients=;
if(benchtime==) benchtime=; /* Copyright */
fprintf(stderr,"Webbench - Simple Web Benchmark "PROGRAM_VERSION"\n"
"Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.\n"
); /**
* 创建发送给http服务器的请求头
*/
build_request(argv[optind]); /* print bench info */
/**
* 接下来这部分都是打印出初步解析出来的数据,可以用来检查是否符合要求
*/
printf("\nBenchmarking: ");
switch(method)
{
case METHOD_GET:
default:
printf("GET");break;
case METHOD_OPTIONS:
printf("OPTIONS");break;
case METHOD_HEAD:
printf("HEAD");break;
case METHOD_TRACE:
printf("TRACE");break;
}
printf(" %s",argv[optind]);
switch(http10)
{
case : printf(" (using HTTP/0.9)");break;
case : printf(" (using HTTP/1.1)");break;
}
printf("\n");
if(clients==)
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"); /**
* 调用bench函数,完成相应的功能
*/
return bench();
} /**
* build_request函数完成功能:
* 1. 初始化host和request数组;
* 2. 检查给出的url参数是否合法;
* 3. 合成对应http协议的请求头;
*/
void build_request(const char *url)
{
/**
* 局部变量说明:
* 1. tmp : 用于存储端口号;
* 2. i : 循环计数;
*/
char tmp[];
int i; /**
* 初始化host和request数组,为下面的操作作准备
*/
bzero(host,MAXHOSTNAMELEN);
bzero(request,REQUEST_SIZE); /**
* 不同的请求方式,对应不同的协议标准,这里相当于校正请求协议
*/
if(force_reload && proxyhost!=NULL && http10<)
http10=;
if(method==METHOD_HEAD && http10<)
http10=;
if(method==METHOD_OPTIONS && http10<)
http10=;
if(method==METHOD_TRACE && http10<)
http10=; switch(method)
{
default:
case METHOD_GET: strcpy(request,"GET");break;
case METHOD_HEAD: strcpy(request,"HEAD");break;
case METHOD_OPTIONS: strcpy(request,"OPTIONS");break;
case METHOD_TRACE: strcpy(request,"TRACE");break;
} strcat(request," "); /**
* url中如果不存在"://"说明是非法的URL地址
*/
if(NULL==strstr(url,"://"))
{
fprintf(stderr, "\n%s: is not a valid URL.\n",url);
exit();
} /**
* url字符串长度不能长于1500字节
*/
if(strlen(url)>)
{
fprintf(stderr,"URL is too long.\n");
exit();
} /**
* 如果没有设置代理服务器,并且协议不是http,说明出错了.
*/
if(proxyhost==NULL)
if (!=strncasecmp("http://",url,))
{
fprintf(stderr,"\nOnly HTTP protocol is directly supported, set --proxy for others.\n");
exit();
} /* protocol/host delimiter */
/**
* 接下来是解析URL并合成请求行
*/ i=strstr(url,"://")-url+;
/* printf(" %d\n",i); */ //如果url = "http://www.baidu.com:80/", i = 7
if(strchr(url+i,'/')==NULL)
{
fprintf(stderr,"\nInvalid URL syntax - hostname don't ends with '/'.\n");
exit();
} /**
* 这段代码主要完成一下内容:
* 1. 如果是通过代理服务器对服务器进行访问,那么proxyhost和proxyport就直接
* 是代理服务器的IP和端口号;
* 2. 如果是直接访问目标服务器,则需要从URL地址中解析出IP(或者域名)和端口号;
*/
if(proxyhost==NULL)
{
/* get port from hostname */
if(index(url+i,':')!=NULL &&
index(url+i,':')<index(url+i,'/'))
{
//获取host主机域名
strncpy(host,url+i,strchr(url+i,':')-url-i); //没有给出端口号,就直接是用默认的端口号: 80
bzero(tmp,);
strncpy(tmp,index(url+i,':')+,strchr(url+i,'/')-index(url+i,':')-);
/* printf("tmp=%s\n",tmp); */
proxyport=atoi(tmp);
if(proxyport==) proxyport=;
}
else
{
/**
* 获取host主机域名,没有给出端口号,就直接是用默认的端口号: 80
*/
strncpy(host,url+i,strcspn(url+i,"/"));
}
// printf("Host=%s\n",host);
strcat(request+strlen(request),url+i+strcspn(url+i,"/")); //这里是获取URI
} else
{
// printf("ProxyHost=%s\nProxyPort=%d\n",proxyhost,proxyport);
// 代理服务器需要完整的URL去访问服务器,而不仅仅是URI
strcat(request,url);
} /**
* 当前的使用的http协议的版本
*/
if(http10==)
strcat(request," HTTP/1.0");
else if (http10==)
strcat(request," HTTP/1.1");
strcat(request,"\r\n"); /**
* 到这里请求行就已经合成完毕了,接下来要合成消息头
*/
if(http10>)
strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"\r\n");
if(proxyhost==NULL && http10>)
{
strcat(request,"Host: ");
strcat(request,host);
strcat(request,"\r\n");
}
/**
* 不缓存请求页面,查资料说是对浏览器有效,难道服务器也需要,
* 不知为何这里也需要?
*/
if(force_reload && proxyhost!=NULL)
{
strcat(request,"Pragma: no-cache\r\n");
}
/**
* 使用短连接,即服务器返回后就断开连接
*/
if(http10>)
strcat(request,"Connection: close\r\n"); /* add empty line at end */
/**
* 按不同http协议要求,是否空出一行,下面是请求实体,如果是post请求,
* 需要把请求参数放在这部分.到这里,消息头也就合成完了,接下
* 来就是是用这个请求头去访问http服务器了
*/
if(http10>) strcat(request,"\r\n");
// printf("Req=%s\n",request);
} /* vraci system rc error kod */
/**
* bench函数完成以下功能:
* 1. 试探性的尝试一次是否能够正常连接服务器,如果连接失败,也就没必要继续后续处理了;
* 2. 创建管道,用于父子进程通信;
* 3. 创建clients对应数量的子进程;
* 4. 子进程:
* 1. 对服务器进行benchtime秒的连接访问,获取对应的failed,speed,bytes值;
* 2. 当时间到了benchtime秒以后,打开写管道;
* 3. 将子进程自己测试得到的failed,speed,bytes值发送给父进程;
* 4. 关闭写管道文件描述符;
* 5. 父进程:
* 1. 打开读管道;
* 2. 设置管道一些参数,初始化父进程的failed,speed,bytes变量;
* 3. while循环不断去获取子进程传输过来的数据,直到子进程全部退出;
* 4. 关闭读管道;
* 5. 对数据进行处理,并打印输出;
*/
static int bench(void)
{
/**
* 局部变量说明:
* 1. i : for循环暂存变量,这里也暂存了一下阿socket文件描述符,
* 还暂存从子进程传给父进程的speed数据;;
* 2. j : 暂存从子进程传给父进程的failed数据;
* 3. k : 暂存从子进程传给父进程的byttes数据;
* 4. pid : fork()出子进程时,保存进程描述符的;
* 5. f : 保存打开的管道的文件指针;
*/
int i,j,k;
pid_t pid=;
FILE *f; /* check avaibility of target server */
/**
* 测试一下我们要测试的服务器是否能够正常连接.
* Socket函数完成的工作:
* 1. 转换IP,域名,填充struct sockaddr_in,获取对应的socket描述符;
* 2. 连接服务器;
*/
i=Socket(proxyhost==NULL?host:proxyhost,proxyport);
if(i<) {
fprintf(stderr,"\nConnect to server failed. Aborting benchmark.\n");
return ;
}
close(i); /* create pipe */
/**
* 创建管道,主要用于父进程和子进程通信
*/
if(pipe(mypipe))
{
perror("pipe failed.");
return ;
} /* not needed, since we have alarm() in childrens */
/* wait 4 next system clock tick */
/*
cas=time(NULL);
while(time(NULL)==cas)
sched_yield();
*/ /* fork childs */
for(i=;i<clients;i++)
{
pid=fork();
/**
* 子进程获取到的pid=0,所以子进程会理解跳出循环
* 不会再创建子进程,而父进程则会跳过这个判断,继续
* 创建子进程,知道数量达到clients的值.
*/
if(pid <= (pid_t) )
{
/* child process or error*/
sleep(); /* make childs faster */
break;
}
} //创建子进程失败
if( pid< (pid_t) )
{
fprintf(stderr,"problems forking worker no. %d\n",i);
perror("fork failed.");
return ;
} /**
* 这一部分完成的工作:
* 1. 子进程:
* 1. 对服务器进行benchtime秒的连接访问,获取对应的failed,speed,bytes值;
* 2. 当时间到了benchtime以后,打开写管道;
* 3. 将子进程自己测试得到的failed,speed,bytes值发送给父进程;
* 4. 关闭写管道文件描述符;
* 2. 父进程:
* 1. 打开读管道;
* 2. 设置管道一些参数,初始化父进程的failed,speed,bytes变量;
* 3. while循环不断去获取子进程传输过来的数据,直到子进程全部退出;
* 4. 关闭读管道;
* 5. 对数据进行处理,并打印输出;
*/ if(pid== (pid_t) )
{
/* I am a child */
if(proxyhost==NULL)
benchcore(host,proxyport,request);
else
benchcore(proxyhost,proxyport,request); /* write results to pipe */
f=fdopen(mypipe[],"w");
if(f==NULL)
{
perror("open pipe for writing failed.");
return ;
}
/* fprintf(stderr,"Child - %d %d\n",speed,failed); */
fprintf(f,"%d %d %d\n",speed,failed,bytes);
fclose(f);
return ;
}
else
{
f=fdopen(mypipe[],"r");
if(f==NULL)
{
perror("open pipe for reading failed.");
return ;
}
setvbuf(f,NULL,_IONBF,); //设置管道为无缓冲类型
speed=;
failed=;
bytes=; while()
{
pid=fscanf(f,"%d %d %d",&i,&j,&k);
if(pid<)
{
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==) 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;
} /**
* benchcore函数完成功能:
* 1. 注册闹钟处理函数,设置闹钟时间,具体时间由benchtime给出,默认是30s;
* 2. while循环里判断闹钟时间是否到了,如果到了退出循环;
* 3. while循环里连接服务器;
* 4. while循环里发送http请求头给服务器;
* 5. while循环里判断是否需要接受服务器数据;
* 6. 关闭与服务器的连接;
* 7. 在整个过程中,以下变量会统计在benchtime给出的时间内的一些信息:
* 1. failed : 连接服务器失败和传输数据过程中失败的连接数;
* 2. speed : 正常连接服务器,并且正常传输数据的连接数
* 3. bytes : 从服务器获取到的字节数;
*/
void benchcore(const char *host,const int port,const char *req)
{
/**
* 局部变量说明:
* 1. rlen : 请求字符串的长度;
* 2. buf : 保存从服务器获取的数据;
* 3. s : socket文件描述符;
* 4. i : 保存从服务器读到的字节数;
* 5. sa : 信号结构体变量;
*/
int rlen;
char buf[];
int s,i;
struct sigaction sa; /* setup alarm signal handler */
/**
* 注册闹钟信号处理函数,并设置闹钟时间为benchtime,默认是30s;
*/
sa.sa_handler=alarm_handler;
sa.sa_flags=;
if(sigaction(SIGALRM,&sa,NULL))
exit();
alarm(benchtime); rlen=strlen(req);
nexttry:
while()
{
if(timerexpired) //检查闹钟时间是否到了,如果到了,子进程就退出
{
if(failed>)
{
/* fprintf(stderr,"Correcting failed by signal\n"); */
failed--;
}
return;
} s=Socket(host,port);
if(s<)
{
failed++;
continue;
} /**
* 将请求头发给web服务器
*/
if(rlen!=write(s,req,rlen))
{
/**
* 写数据失败,代表当前连接有问题,也就是失败了
*/
failed++;
close(s);
continue;
} if(http10==) // http/0.9协议
if(shutdown(s,))
{
failed++;
close(s);
continue;
} if(force==) //是否读取服务器返回数据
{
/* read all available data from socket */
while()
{
if(timerexpired) break; //判断是否已经闹钟到时
i=read(s,buf,);
/* fprintf(stderr,"%d\n",i); */
/**
* 对当前次连接数据读取错误,那么重来
*/
if(i<)
{
failed++;
close(s);
goto nexttry;
}
else
if(i==)
break;
else
bytes+=i; //统计一共读取了多少字节
}
} /**
* 关闭socket文件,如果出错,那么增加失败的统计数据
*/
if(close(s))
{
failed++;
continue;
}
/**
* 成功完成连接,数据传输,获取等等工作,speed统计数据+1
*/
speed++;
}
}

webbench-1.5_hacking的更多相关文章

  1. Webbench性能测试

    1.下载安装:立即下载  官网:http://home.tiscali.cz/~cz210552/webbench.html 2.解压缩:tar -zxvf webbench-1.5.tar.gz 3 ...

  2. webbench之使用(二)

    [root@lam7 ~]# webbench -helpwebbench [option]... URL -f|--force                Don't wait for reply ...

  3. webbench之编译安装(一)

    1.编译安装:   1 2 3 4 [root@hexuweb102 ~]$wget http://blog.s135.com/soft/linux/webbench/webbench-1.5.tar ...

  4. Linux下四款Web服务器压力测试工具(http_load、webbench、ab、siege)介绍

    一.http_load程序非常小,解压后也不到100Khttp_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载.但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会把 ...

  5. linux下如何安装webbench

    1.上传webbench,解压 2.make&&make install进行安装 如果报没有man1目录,则要用 mkdir -p /usr/local/man/man1 然后 mak ...

  6. 网站压力测试工具webbench使用说明

    一.webbench简介        Webbench是有名的网站压力测试工具,它是由Lionbridge公司(http://www.lionbridge.com)开发.它的帮助文件和文档请到:ww ...

  7. WebBench源码分析与心得

    源码:https://github.com/EZLippi/WebBench   关键全局变量: speed 成功次数 failed 失败次数 bytes 接收字节数 benchtime 执行时长(秒 ...

  8. webbench 压力测试

    原文 webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好用,安装使用也特别方便,并且非常小. 主要是 -t 参数用着比较爽,下面参考了张宴 ...

  9. 压力测试 webbench

    Linux下 webbench最多可以模拟3万个并发连接去测试网站的负载能力 webbench -c -t http://127.0.0.1/phpinfo.php 说明: -c 客户端数量(并发数量 ...

随机推荐

  1. 装B必备之 快捷键配置

    作为一个程序员 所有程序都用快捷来这是装B必备的无形装B 最为致命.... 开始搞起 第一步配置环境变量 在系统D盘新建一个文件夹  D:\cache; 然后把这个路径 配置上 D:\cache; 最 ...

  2. elementUI和iview兼容么

    听说iview的作者居然是91年的,我要赶快加油了. https://zhuanlan.zhihu.com/p/25739512

  3. Myeclipse2016安装Aptana

    Myeclipse2016安装Aptana 想装个Aptana,装了半天,网上说的什么links方式啊,在线方式啊,都是什么的浮云. 所以自己来写个安装教程. 一.Aptana简要介绍 Aptana有 ...

  4. 解决Word 2013, Word 2016的保存太慢的问题

    尝试下面步骤: 方法 一:文件〉选项〉高级〉,保存,关闭“允许后台保存”选项. 提示:禁止该项功能可能存在风险, 请及时保存文件. 方法二:禁用 Office  中的硬件加速 1.启动任一 Offic ...

  5. R语言-attach、detach、with

    在R语言中,对于串列,数据框中的数据的进行操作时,为了避免重复地键入对象名称,可使用attach或with. 1.attach() 假设data.frame包含列name,age attach(one ...

  6. C# Arc Gis实例教程——网络链接

    http://www.doc88.com/p-305888679879.html http://www.doc88.com/p-992232217007.html http://www.cnblogs ...

  7. English trip -- VC(情景课)9 A Get ready

    She is doing homwork He is doing laundry He is drying the dishes She is making lunch She is making t ...

  8. android----AsyncHttpClient的get,post和图片上传

    async-http-client库是一个基于回调函数的Http异步通信客户端Android组件,是在Apache的HttpClient库的基础上开发构建而成的. Eclipse使用:导入androi ...

  9. python中的注意事项

    .python 中的 and 从左到右计算表达式,若所有值均为真,则返回最后一个值,若存在假,返回第一个假值: or 也是从左到有计算表达式,返回第一个为真的值: 其中数字 0 是假,其他都是真: 字 ...

  10. Eclipse 汉化方法

    1 打开 http://www.eclipse.org/babel/downloads.php 2  复制 http://download.eclipse.org/technology/babel/u ...