webbench简介

webbench由C语言写成的用于网站压力测试的一个非常简单的工具,它最多可以模拟30000个并发连接去进行测试。

webbench的安装和使用可以自行百度,也可以过下这篇文章

 

webbench执行流程

命令行解析 --> 构建HTTP请求包 --> 创建指定数量的工作进程 --> 每个工作进程对测试网站在测试时间内持续发送请求/接收响应

 

具体分析

1. 命令行解析。

  这里主要用到了getopt库。getopt库是C中常用的命令行解析库,具有如下一些常用的全局变量、结构体以及函数。

/* 常用全局变量 */

extern char*   optarg;    // 指向获取的option
extern int     optind;    // 已经解析过的option的个数     
extern int     opterr;    // 错误码
extern int     optopt;
/* 结构体:解析option时主要的结构体,用以指明有哪些指定options */

struct option {
    const char*    name;
    int            has_arg;
    int*           flag;
    int            val;      
};

/* has_arg的几个宏 */
#define no_argument       0
#define require_argument  1
#define optional_argument 2
/* 常用的几个函数 */

int getopt();

int getopt_long(int __argc, char* const* __argv, const char* __shortopts, const struct option* __longopts, int* __longind);

int getopt_long_only(int __argc, char* const* __argv, const char* __shortopts, const struct option* __longopts, int* __longind);

2. 构建HTTP请求包。

  代码调用了build_request函数对HTTP请求包进行了构建。常见的HTTP请求包构建规则:

  请求方法 URL 协议版本 \r\n

   头部字段名: 值  \r\n

    ....

   头部字段名: 值  \r\n

   \r\n

   \r\n

  请求数据

  请求方法:GET, POST, HEAD, PUT, DELETE, TRACE, CONNECT, OPTIONS

  协议版本:HTTP/1.0   HTTP/1.1

  头部: User-agent, Host, Pragma, Connection等等

3. 使用fork创建指定数量的工作进程,用pipe让主进程和工作进程建立通信,以便于主进程收集子进程的测试信息。

/* 使用fork创建多进程代码片段 */

static int bench(void)
{
    ...
    for (i = 0; i < clients; i++)
    {
        pid = fork();
        if (pid <= 0)  // 如果是子进程或者fork失败了,退出这个循环 
        {
             sleep(1);
             break;
        }
    }

    ...   
}
/* fork 函数声明 */

#include <unistd.h>
#include <sys/types.h>

pid_t fork(void);   // pid_t 在 sys/types.h 中定义


/* pipe 函数声明 */
#include <unistd.h>

int pipe(int pipefd[2]);


/* fdopen 函数声明 */
#include <stdio.h>

FILE *fdopen(int fd, const char *mode); // 打开 pipe 文件 

4. 每个进程模拟一个客户端,创建socket并连接测试web,用alarm定时测试时长,在这个时间段里,客户端持续向web请求并接收响应。

 这里有几点要注意:

  a) 在客户端的socket需要两步完成对web的连接:创建一个socket(使用socket()函数);连接web(使用connect()函数)。

  b) alarm定时时长,输入的参数只能是秒数。当定时时间到了的时候,系统会发送一个SIGALRM信号给alarm所在的进程,所以在调用alarm之前,需要注册一个信号函数sigaction或signal(代码中使用了sigaction),将SIGALRM与回调函数绑定,当系统发送SIGALRM,会调用相应的回调函数(代码中使用了alarm_handler)进行处理。

上面几个函数的声明如下

/* socket, connect 函数声明 */
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);


/* alarm 函数声明 */
#include <unistd.h>

unsigned int alarm(unsigned int seconds);


/* sigaction 函数声明 */
#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigation *oldact);

struct sigaction {
    void          (*sa_handler)   (int);
    void          (*sa_sigaction) (int, siginfo_t*, void*);
    sigset_t      sa_mask;
    int           sa_flag;
    void          (*sa_restorer)  (void);
};

 

完!

2018-03-21 23:39:46

posted on 2018-03-21 23:45  o小小程序猿o  阅读(240)  评论(0编辑  收藏  举报