Webbench是有名网站压力测试工具,它是由Lionbridge公司开发
(http://www.lionbridge.com)
Webbench能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。webbench的标准测试可以向我们展示服务器的两项内容:每秒钟相应请求数和每秒钟传输数据量。webbench不但能具有便准静态页面的测试能力,还能对动态页面(ASP,PHP,JAVA,CGI)进 行测试的能力。还有就是他支持对含有SSL的安全网站例如电子商务网站进行静态或动态的性能测试。
Webbench最多可以模拟3万个并发连接去测试网站的负载能力。
webbench的源码很简单,只有socket.c和webbench.c两个文件,加起来也就500行左右的代码。
实例:
流程图如下:
整个代码主要有以下几个函数:
int Socket(const char *host, int clientPort):建立socket连接
void usage(void):使用说明
void build_request(const char *url):构造http请求
static int bench(void):,创建管道,对http请求进行测试
void benchcore(const char *host,const int port,const char *req):测试http请求
//socket.c 文件
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
/*
函数功能:建立socket连接,返回-1连接失败,成功返回socket描述符
host:网络地址
clientPort:端口
*/
int Socket(const char *host, int clientPort)
{
int sock;
unsigned long inaddr;
struct sockaddr_in ad;//声明一个ipv4地质类型的结构体
struct hostent *hp;
memset(&ad, 0, sizeof(ad));
ad.sin_family = AF_INET;//设置为流式(TCP协议数据传输方式)
inaddr = inet_addr(host);
/*
点分十进制的IP地址转换成网络中传输的长整型数。如果传入的字符串不是一个合法的IP地址,
将返回INADDR_NONE,INADDR_NONE是255.255.255.255 是一个无效地址
*/
if (inaddr != INADDR_NONE)//判断是否为合法IP地址
memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));//转换后的IP拷贝到ad结构体
else
{
//如果不是IP地址而是域名
hp = gethostbyname(host);//通过域名获取IP地址
//gethostbyname(),返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针。
if (hp == NULL)
return -1;
memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
}
ad.sin_port = htons(clientPort);//设置端口号
//htons(),将一个无符号短整型的主机数值转换为网络字节
sock = socket(AF_INET, SOCK_STREAM, 0);//申请一个套接字
//socket(),获取文件描述符,成功返回一个套接字描述符,失败返回-1
if (sock < 0)
return sock;
if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0)//和刚才的ad结构体建立连接,也就是和host建立连接
return -1;
/*
connet(),用于建立与指定socket的连接
参数1:标识一个未连接的socket
参数2:指向要连接套接字的sockaddr结构体的指针
参数3:sockadd人结构体的字节长度
*/
return sock;
}
//webbench.c文件
#include "socket.c"
#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=0;//用来检测时长是否到达指定时长
int speed=0;//记录服务器响应的数量
int failed=0;//记录请求失败的数量
int bytes=0;//记录读取成功的字节数
/* globals */
int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */
/* 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"
//请求方法设为GET,此外还支持OPTIONS,HEAD,TRACE等方法
int method=METHOD_GET;
int clients=1;//并发数,由命令行参数-c指定,默认为1
int force=0;//是否等待服务器应答
int force_reload=0;//是否使用cache,默认为0,使用
int proxyport=80;//代理服务器端口号,默认80
char *proxyhost=NULL;//代理服务器地址
int benchtime=30;//测试时间,由命令行参数-t指定,默认为30秒
/* internal */
int mypipe[2];//创建管道,用于父子进程间通信
char host[MAXHOSTNAMELEN];//主机名
#define REQUEST_SIZE 2048
char request[REQUEST_SIZE];//HTTP请求信息
/*
struct option类型数组.该数据结构中的每个元素对应了一个长选项,并且每个元素是由四个域组成。通常情况下,可以按以下规则使用:
第一个元素,描述长选项的名称;第二个选项,代表该选项是否需要跟着参数,需要参数则为1,反之为0;第三个选项,可以赋为NULL
;第四个选项,是该长选项对应的短选项名称。另外,数据结构的最后一个元素,要求所有域的内容均为0,即{NULL,0,NULL,0}。
结构中的元素解释如下:
1)const char *name:选项名,前面没有短横线。譬如"help"、"verbose"之类。
2)int has_arg:描述长选项是否有选项参数,如果有,是哪种类型的参数,其值见下表:
符号常量 数值 含义
no_argument 0 选项没有参数
required_argument 1 选项需要参数