webbench源码注释.docx
- 文档编号:24918291
- 上传时间:2023-06-02
- 格式:DOCX
- 页数:26
- 大小:25.86KB
webbench源码注释.docx
《webbench源码注释.docx》由会员分享,可在线阅读,更多相关《webbench源码注释.docx(26页珍藏版)》请在冰豆网上搜索。
webbench源码注释
文件:
webbench.c
/*
*(C)RadimKolar1997-2004
*Thisisfreesoftware,seeGNUPublicLicenseversion2for
*details.
*
*SimpleforkingWWWServerbenchmark:
*
*Usage:
*webbench--help
*
*Returncodes:
*0-sucess
*1-benchmarkfailed(serverisnoton-line)
*2-badparam
*3-internalerror,forkfailed
*
*/
#include"socket.c"
#include
#include
#include
#include
#include
#include
#include
/*values*/
/**注**:
volatile是易变的,不稳定的意思。
volatile是关键字,是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其他线程等,遇到这个关键字声明的变量,编译器对访问该变量的代码不再进行优化,从而可以提供对特殊地址的稳定访问。
**/
volatileinttimerexpired=0;//根据测试时间判断是否超时
intspeed=0;//服务器响应数
intfailed=0;//请求失败数
intbytes=0;//读取字节数
/*globals*/
inthttp10=1;//http协议版本;0为http/0.9,1为http/1.0,2为http/1.1
/*Allow:
GET,HEAD,OPTIONS,TRACE*/
#defineMETHOD_GET0
#defineMETHOD_HEAD1
#defineMETHOD_OPTIONS2
#defineMETHOD_TRACE3
#definePROGRAM_VERSION"1.5"
//定义HTTP请求方法GET,此外还支持OPTIONS、HEAD、TRACE方法
intmethod=METHOD_GET;
intclients=1;//并发数;由命令行参数-c指定,默认为1
intforce=0;//是否等待服务器应答
intforce_reload=0;//是否使用cache,默认为0,使用
intproxyport=80;//代理服务器端口号,默认为80
char*proxyhost=NULL;//代理服务器地址
intbenchtime=30;//测试时间;由命令行参数-t指定,默认为30s
/*internal*/
intmypipe[2];//创建管道;用于父子进程间通信,读写数据
charhost[MAXHOSTNAMELEN];//主机名
#defineREQUEST_SIZE2048
charrequest[REQUEST_SIZE];//HTTP请求信息
/**注**:
structoption类型数组。
说明:
该数据结构中的每个元素对应了一个长选项,并且每个元素是由四个域组成。
通常情况下,可以按以下规则使用。
第一个元素,描述长选项的名称;第二个选项,代表该选项是否需要跟着参数,需要参数则为1,反之为0;第三个选项,可以赋为NULL;第四个选项,是该长选项对应的短选项名称。
另外,数据结构的最后一个元素,要求所有域的内容均为0,即{NULL,0,NULL,0}。
结构中的元素解释如下:
1)constchar*name:
选项名,前面没有短横线。
譬如"help"、"verbose"之类。
2)inthas_arg:
描述长选项是否有选项参数,如果有,是哪种类型的参数,其值见下表:
符号常量数值含义
no_argument0选项没有参数
required_argument1选项需要参数
optional_argument2选项参数是可选的
3)int*flag:
如果该指针为NULL,那么getopt_long返回val字段的值;
如果该指针不为NULL,那么会使得它所指向的结构填入val字段的值,同时getopt_long返回0
4)intval:
如果flag是NULL,那么val通常是个字符常量,如果短选项和长选项一致,那么该字符就应该与optstring中出现的这个选项的参数相同;**/
//structoption结构体,配合getopt_long函数使用
staticconststructoptionlong_options[]=
{
{"force",no_argument,&force,1},
{"reload",no_argument,&force_reload,1},
{"time",required_argument,NULL,'t'},
{"help",no_argument,NULL,'?
'},
{"http09",no_argument,NULL,'9'},
{"http10",no_argument,NULL,'1'},
{"http11",no_argument,NULL,'2'},
{"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,0,NULL,0}
};
/*prototypes*/
staticvoidbenchcore(constchar*host,constintport,constchar*request);
staticintbench(void);
staticvoidbuild_request(constchar*url);
/*******************************************
**函数功能:
信号处理函数
*/
staticvoidalarm_handler(intsignal)
{
timerexpired=1;//timerexpired置1
}
/*******************************************
**函数功能:
程序使用说明
*/
staticvoidusage(void)
{
fprintf(stderr,
"webbench[option]...URL\n"
"-f|--forceDon'twaitforreplyfromserver.\n"
"-r|--reloadSendreloadrequest-Pragma:
no-cache.\n"
"-t|--time
"-p|--proxy port>Useproxyserverforrequest.\n" "-c|--clients "-9|--http09UseHTTP/0.9stylerequests.\n" "-1|--http10UseHTTP/1.0protocol.\n" "-2|--http11UseHTTP/1.1protocol.\n" "--getUseGETrequestmethod.\n" "--headUseHEADrequestmethod.\n" "--optionsUseOPTIONSrequestmethod.\n" "--traceUseTRACErequestmethod.\n" "-? |-h|--helpThisinformation.\n" "-V|--versionDisplayprogramversion.\n" ); }; /******************************************* **主函数 */ intmain(intargc,char*argv[]) { intopt=0; intoptions_index=0; char*tmp=NULL; /**注**: argc: 指命令行输入参数的个数;argv: 存储所有命令行参数,字符串数组**/ if(argc==1)//不带参数时,输出使用说明 { usage();//调用usage()函数: 使用说明 return2; } /*注: getopt_long函数: 用来解析命令行参数,支持长命令选项。 参数1、2: main函数的argc、argv参数; 参数3: 由该命令要处理的各个选项组成的字符串。 选项后面带有冒号时,表示该选项是一个带参数的选项; 参数4: 构造体structoption数组; 参数5: 输出参数,函数getopt_long()返回时,该参数的值是structoption数组的索引 optarg: 处理带输入参数的选项时,选项参数保存至char*optarg中。 optind: 下一个处理的选项在argv中的地址,所有选项处理完后,optind指向未识别的项。 optopt: 最后一个已知项。 */ //检查输入参数,并设置对应选项 while((opt=getopt_long(argc,argv,"912Vfrt: p: c: ? h",long_options,&options_index))! =EOF) { switch(opt)//相应的命令行参数 { case0: break; case'f': force=1;break; case'r': force_reload=1;break; case'9': http10=0;break; case'1': http10=1;break; case'2': http10=2;break; case'V': printf(PROGRAM_VERSION"\n");exit(0);//输出版本号 //optarg表示命令后的参数,例如-c100,optarg为100 case't': benchtime=atoi(optarg);break; case'p': /*proxyserverparsingserver: port*/ /**注**: strrchr函数。 找一个字符c在另一个字符串str中末次出现的位置(也就是从str的右侧开始查找字符c首次出现的位置),并返回从字符串中的这个位置起,一直到字符串结束的所有字符。 如果未能找到指定字符,那么函数将返回NULL**/ tmp=strrchr(optarg,': '); proxyhost=optarg;//地址设定 if(tmp==NULL) { break; } if(tmp==optarg) { //fprintf函数: 格式化输出到文件 fprintf(stderr,"Errorinoption--proxy%s: Missinghostname.\n",optarg); return2; } if(tmp==optarg+strlen(optarg)-1) { fprintf(stderr,"Errorinoption--proxy%sPortnumberismissing.\n",optarg); return2; } *tmp='\0'; proxyport=atoi(tmp+1);break;//重设端口号 case': ': case'h': case'? ': usage();return2;break; case'c': clients=atoi(optarg);break;//并发数 } } //optind: 命令行参数中未读取的下一个元素下标 if(optind==argc){ fprintf(stderr,"webbench: MissingURL! \n"); usage(); return2; } //并发数和测试时间不能为0 if(clients==0)clients=1; if(benchtime==0)benchtime=60; /*Copyright*/ fprintf(stderr,"Webbench-SimpleWebBenchmark"PROGRAM_VERSION"\n" "Copyright(c)RadimKolar1997-2004,GPLOpenSourceSoftware.\n" ); build_request(argv[optind]);//封装HTTP请求信息 /*printbenchinfo*/ //输出提示信息 printf("\nBenchmarking: "); switch(method) { caseMETHOD_GET: default: printf("GET");break; caseMETHOD_OPTIONS: printf("OPTIONS");break; caseMETHOD_HEAD: printf("HEAD");break; caseMETHOD_TRACE: printf("TRACE");break; } printf("%s",argv[optind]); switch(http10) { case0: printf("(usingHTTP/0.9)");break; case2: printf("(usingHTTP/1.1)");break; } printf("\n"); if(clients==1)printf("1client"); else printf("%dclients",clients);//并发数 printf(",running%dsec",benchtime);//测试时间 if(force)printf(",earlysocketclose"); if(proxyhost! =NULL)printf(",viaproxyserver%s: %d",proxyhost,proxyport); if(force_reload)printf(",forcingreload"); printf(".\n"); returnbench();//开始测试 } /********************************************* **函数功能: 封装HTTP请求信息 **@url: URL地址 **备注: 封装好的HTTP请求信息存放在数组request */ voidbuild_request(constchar*url) { chartmp[10]; inti; /**注**: bzero函数。 原型: externvoidbzero(void*s,intn);功能: 置字节字符串s的前n个字节为零**/ //请求地址和请求连接初始化清零 bzero(host,MAXHOSTNAMELEN); bzero(request,REQUEST_SIZE); //设置HTTP协议版本 if(force_reload&&proxyhost! =NULL&&http10<1)http10=1; if(method==METHOD_HEAD&&http10<1)http10=1; if(method==METHOD_OPTIONS&&http10<2)http10=2; if(method==METHOD_TRACE&&http10<2)http10=2; //设置HTTP请求方法 switch(method) { default: caseMETHOD_GET: strcpy(request,"GET");break; caseMETHOD_HEAD: strcpy(request,"HEAD");break; caseMETHOD_OPTIONS: strcpy(request,"OPTIONS");break; caseMETHOD_TRACE: strcpy(request,"TRACE");break; } strcat(request,""); //判断URL地址是否合法 if(NULL==strstr(url,": //"))//判断URL地址是否包含“: //” { //错误信息 fprintf(stderr,"\n%s: isnotavalidURL.\n",url); exit (2); } if(strlen(url)>1500)//判断URL长度是否太长 { //错误信息 fprintf(stderr,"URListoolong.\n"); exit (2); } if(proxyhost==NULL)//判断是否有代理服务器 if(0! =strncasecmp("http: //",url,7))//判断前7个字符串是否为http: // { //错误信息 fprintf(stderr,"\nOnlyHTTPprotocolisdirectlysupported,set--proxyforothers.\n"); exit (2); } /*protocol/hostdelimiter*/ i=strstr(url,": //")-url+3;//指向http: //后第一个位置,即主机名 if(strchr(url+i,'/')==NULL){//判断URL地址是否以“/”结尾 //错误信息 fprintf(stderr,"\nInvalidURLsyntax-hostnamedon'tendswith'/'.\n"); exit (2); } if(proxyhost==NULL) { /*getportfromhostname*/ /**注**: index()函数。 功能: 用来找出参数s字符串中第一个出现的参数c地址,然后将该字符出现的地址返回**/ if(index(url+i,': ')! =NULL&&index(url+i,': ') { strncpy(host,url+i,strchr(url+i,': ')-url-i);//主机地址 bzero(tmp,10); strncpy(tmp,index(url+i,': ')+1,strchr(url+i,'/')-index(url+i,': ')-1);//端口号 proxyport=atoi(tmp);//类型转换 if(proxyport==0)proxyport=80; } else { strncpy(host,url+i,strcspn(url+i,"/")); } /**注**: strcspn: 返回str1和str2中不同的元素的个数**/ strcat(request+strlen(request),url+i+strcspn(url+i,"/")); } else { strcat(request,url);//URL地址 } //开始封装HTTP请求信息 if(http10==1)//版本号 strcat(request,"HTTP/1.0"); elseif(http10==2) strcat(request,"HTTP/1.1"); strcat(request,"\r\n");//\r\n: 回车换行 if(http10>0)//User-Agent: strcat(request,"User-Agent: WebBench"PROGRAM_VERSION"\r\n"); if(proxyhost==NULL&&http10>0)//Host: { strcat(request,"Host: "); strcat(request,host);//URL地址 strcat(request,"\r\n"); } if(force_reload&&proxyhost! =NULL)//Pragma: { strcat(request,"Pragma: no-cache\r\n"); } if(http10>1)//Connection: strcat(request,"Connection: close\r\n"); /*addemptylineatend*/ if(http10>0)strcat(request,"\r\n"); //printf("Req=%s\n",request); } /************
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- webbench 源码 注释