写的一个 C 网站压力测试工具
作者 斯人 | 发布于 2012 年 2 月 29 日

前几天写的一个 网站压力测试工具…
只是拿来测试…功能与webbench类似..
但是有一些功能没有做,如代理啊等等.
程序采用 多进程,
放出源码 …有一些BUG,目前还没有时间改,给大家参考学习用

/*
 * =====================================================================================
 *
 *       Filename:  bench.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  02/07/12 11:59:40
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  SiRen (), siren_0203@163.com
 *        Company:  
 *
 * =====================================================================================
 */

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <getopt.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#define BENCH_VERSION "1.0"
#define MAXHOSTLEN 1024
int clients=30;
int benchtime=10;
char host[MAXHOSTLEN];
int port=80;
char request[1024];
int failed=0;
int speed=0;
int timerexpired=0;
int mypipe[2];
void alarm_handler(int signo){
        timerexpired=1;
}
static const struct option option_long[]={
        {"clients",required_argument,NULL,'c'},
        {"time",required_argument,NULL,'t'},
        {"help",no_argument,NULL,'h'},
        {"version",no_argument,NULL,'v'},
        {NULL,0,NULL,0}
};
static void usage();
static void init(char *host);
static void bench();
static int Socket(char *host,int port);
int main(int argc,char *argv[]){
        int opt=0;
        int option_index;
        char *url;
        if(argc==1){
                usage();
                exit(0);
        }
        if((opt=getopt_long(argc,argv,"hvc:t:?",option_long,&option_index))!=EOF){
                switch(opt){
                        case 0:
                        break;
                        case 'c':
                                clients=atoi(optarg)    ;
                        break;
                        case 't':
                                benchtime=atoi(optarg);
                        break;
                        case '?':
                        case 'h':
                                usage();
                        break;
                        case 'v':
                                printf("%c\n",BENCH_VERSION)    ;
                        break;
                }
        }
        url=argv[optind];
        if(NULL==strstr(url,"http://")){
                fprintf(stderr,"%s is not a valid url\n",url)   ;
                exit(0);
        }
        init(url);
        bench();
        return 0;
}
static void init(char *url){
        int i;
        char *tmp;
        //截取 URL  这里去除 http://
        i=strstr(url,"://")-url+3;
        if(NULL==strchr(url+i,'/')){
                printf("URL must be end of /\n")        ;
                exit(0);
        }
        strncpy(host,url+i,strchr(url+i,'/')-url+1);
        strcat(request," ");
        strcat(request,"HTTP/1.1\r\n");
        strcat(request," User-Agent:BENCH WITH SIREN "BENCH_VERSION);
        strcat(request,"\r\n");
        strcat(request," Host:");
        strcat(request,host);
        strcat(request,"\r\n");
        strcat(request," Program:no-cache\r\n");
        strcat(request," Connection:close\r\n");
        if(clients==0)
                clients=30;
        if(benchtime==0)
                benchtime=30;
}
static void bench(){
        pid_t pid;
        int s,len;
        FILE *fp;
        int a,b;
        len=strlen(request);
        for(int i=0;i<clients;i++){
                pid=fork();
                if(pid<=(pid_t)0){
                        sleep(1);
                        break;
                }
        }
        if(pipe(mypipe)){
                fprintf(stderr,"pipe error\n");
                exit(0);
        }
        if(pid==0){
                close(mypipe[0]);
                fp=fdopen(mypipe[1],"w");
                s=Socket(host,port);
                struct sigaction act,oldact;
                act.sa_handler=alarm_handler;
                act.sa_flags=0;

                if(sigaction(SIGALRM,&act,&oldact)<0){
                        fprintf(stderr,"sigaction failed\n");
                        sigaction(SIGALRM,&oldact,NULL);
                        exit(0);
                }
                alarm(benchtime);
                while(1){
                        if(timerexpired==1)
                                break;
                        if(len!=write(s,request,len))   {
                                failed++;
                                fclose(fp);
                                printf("write error\n");
                                return ;
                        }
                        speed++;
                }
                fprintf(fp,"%d %d",speed,failed);
                fclose(fp)      ;
                return ;
        }else{
                wait(0);
                close(mypipe[1]);
                fp=fdopen(mypipe[0],"r");
                fscanf(fp,"%d %d",&a,&b);
                fclose(fp);
                speed+=a;
                failed+=b;
        }
        printf("speed:%d\n failed:%d\n",speed,failed)   ;
}
static void usage(){
        fprintf(stderr,
                        "bench [option]... URL\n"
                        "-c|--clients <n>\n"
                        "-t|--time <sec>\n"
                        "-h|--help\n"
                        "-v|--version\n"
                        )       ;
}
static int Socket(char *host,int port){
        struct sockaddr_in servaddr;
        int socketfd;
        in_addr_t addr;
        struct hostent *hp;
        hp=gethostbyname(host);
        socketfd=socket(AF_INET,SOCK_STREAM,0);
        if(socketfd<0){
                printf("%c\n","failed");
                return socketfd;
        }
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_port=htons(port);
        addr=inet_addr(host);
        servaddr.sin_addr.s_addr=inet_addr("61.135.169.125");
        //memcpy(&(servaddr.sin_addr),&addr,sizeof(addr));
        servaddr.sin_family=AF_INET;
        if(connect(socketfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0){
                return -1;
        }
        return socketfd;
}

使用方法 ./bench -c -t

原文出处:http://www.imsiren.com/archives/285