socket.c文件

所有我自己的注释理解都是汉字,绝大部分前面都有zzy,是为了和原来作者的注释区分开

/* $Id: socket.c 1.1 1995/01/01 07:11:14 cthuang Exp $** This module has been modified by Radim Kolar for OS/2 emx*//***********************************************************************module:       socket.cprogram:      popclientSCCS ID:      @(#)socket.c    1.5  4/1/94programmer:   Virginia Tech Computing Centercompiler:     DEC RISC C compiler (Ultrix 4.1)environment:  DEC Ultrix 4.3 description:  UNIX sockets code.***********************************************************************/#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>int Socket(const char *host, int clientPort)
{int sock;unsigned long inaddr;struct sockaddr_in ad;struct hostent *hp;memset(&ad, 0, sizeof(ad));ad.sin_family = AF_INET;inaddr = inet_addr(host);if (inaddr != INADDR_NONE)//zzy:直接赋值memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));else{//zzy:https://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html函数解释hp = gethostbyname(host);if (hp == NULL)return -1;memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);}ad.sin_port = htons(clientPort);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;
}

webbench.c文件

/** (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"
#include <unistd.h>
#include <sys/param.h>
#include <rpc/types.h>
#include <getopt.h>
#include <strings.h>
#include <time.h>
#include <signal.h>/* values */
//zzy:timerexpired用作是否超时的标志0表示没有超时,1表示超时
volatile int timerexpired=0;
//zzy:speed,failed,bytes 为了方便benchcore的使用,因此设置成全局变量
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"
int method=METHOD_GET;
int clients=1;
//zzy:force和force_load为0表示需要接收到http的响应包,1表示不需要接收
int force=0;
int force_reload=0;int proxyport=80;
char *proxyhost=NULL;
//zzy:默认benchtime
int benchtime=30;
/* internal */
int mypipe[2];
//zzy:MAXHOSTNAMELENDE的值我没有查到明确的答案
char host[MAXHOSTNAMELEN];
#define REQUEST_SIZE 2048
char request[REQUEST_SIZE];//zzy:struct option解释:http://blog.csdn.net/zhuziyu1157817544/article/details/78822247
static const struct option long_options[]=
{//zzy:请注意,凡是不是0的第三个参数,都指向第四个参数,也就是赋值{"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 */
static void benchcore(const char* host,const int port, const char *request);
static int bench(void);
static void build_request(const char *url);//zzy:SIGALRM信号处理函数
static void alarm_handler(int signal)
{timerexpired=1;
}
//zzy:用户使用说明函数
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");
};int main(int argc, char *argv[])
{int opt=0;int options_index=0;char *tmp=NULL;if(argc==1){usage();return 2;} //zzy:函数解释:http://blog.csdn.net/zhuziyu1157817544/article/details/78822247while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF ){switch(opt){case  0 : 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);case 't': benchtime=atoi(optarg);break;      case 'p': //zzy:分解url为ip和port两部分/*proxy server parsing server:port *///zzy:strchr函数http://blog.csdn.net/tommy_wxie/article/details/7554263tmp=strrchr(optarg,':');proxyhost=optarg;if(tmp==NULL){break;}//zzy:没有ip的情况if(tmp==optarg){fprintf(stderr,"Error in option --proxy %s: Missing hostname.\n",optarg);return 2;}//zzy:没有端口的情况if(tmp==optarg+strlen(optarg)-1){fprintf(stderr,"Error in option --proxy %s Port number is missing.\n",optarg);return 2;}*tmp='\0';proxyport=atoi(tmp+1);break;case ':':case 'h':case '?': usage();return 2;break;//zzy:确定client即确定子进程个数case 'c': clients=atoi(optarg);break;}}//zzy:optind==argc代表输入参数中没有要测试的URL//zzy:正常情况下optind = argc -1才对if(optind==argc) {fprintf(stderr,"webbench: Missing URL!\n");usage();return 2;}if(clients==0) clients=1;if(benchtime==0) benchtime=60;/*Copyright */fprintf(stderr,"Webbench - Simple Web Benchmark "PROGRAM_VERSION"\n""Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.\n");//zzy:创建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 0: printf(" (using HTTP/0.9)");break;case 2: printf(" (using HTTP/1.1)");break;}printf("\n");if(clients==1) printf("1 client");elseprintf("%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");//zzy:以上此等打印信息都是检查参数有没有被正确解析//zzy:下面的bench是开始进行压力测试return bench();
}void build_request(const char *url)
{char tmp[10];int i;bzero(host,MAXHOSTNAMELEN);bzero(request,REQUEST_SIZE);/*zzy:针对强关不接受响应包的情况下* 当没有使用代理服务器并且用http0.9协议(默认就是0.9) 改成1.0协议使用*/if(force_reload && proxyhost!=NULL && http10<1) http10=1;/*zzy:涉及参数有输入请求类型的时候* http请求类型介绍:https://www.cnblogs.com/liangxiaofeng/p/5798607.html* 此段是为了确定最终的请求包的http版本* */if(method==METHOD_HEAD && http10<1) http10=1;if(method==METHOD_OPTIONS && http10<2) http10=2;if(method==METHOD_TRACE && http10<2) http10=2;//zzy:构建http包的请求类型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;}//zzy:根据http包的格式,此处应有空格,然后才能追加urlstrcat(request," ");//以下两个if语句监测url是否规范if(NULL==strstr(url,"://")){fprintf(stderr, "\n%s: is not a valid URL.\n",url);exit(2);}if(strlen(url)>1500){fprintf(stderr,"URL is too long.\n");exit(2);}if(proxyhost==NULL)//url头必须是http://开头if (0!=strncasecmp("http://",url,7)) { fprintf(stderr,"\nOnly HTTP protocol is directly supported, set --proxy for others.\n");exit(2);}/*protocol/host delimiter *///zzy:确定http://后面的第一个位置,比如http://www.baidu.com中的第一个w的位置i=strstr(url,"://")-url+3;/*printf("%d\n",i); *///zzy:检查url有没有一个字符/,要求必须至少一个/且不能在url+i的位置if(strchr(url+i,'/')==NULL) {fprintf(stderr,"\nInvalid URL syntax - hostname don't ends with '/'.\n");exit(2);}if(proxyhost==NULL){/* get port from hostname */if(index(url+i,':')!=NULL &&index(url+i,':')<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);/* printf("tmp=%s\n",tmp); */proxyport=atoi(tmp);if(proxyport==0) proxyport=80;}else{strncpy(host,url+i,strcspn(url+i,"/"));}// printf("Host=%s\n",host);strcat(request+strlen(request),url+i+strcspn(url+i,"/"));}else{//printf("ProxyHost=%s\nProxyPort=%d\n",proxyhost,proxyport);strcat(request,url);}//zzy:执行到此出已经构建了http请求行的第二部分if(http10==1)strcat(request," HTTP/1.0");else if (http10==2)strcat(request," HTTP/1.1");strcat(request,"\r\n");//zzy:执行到此出时候,http请求行构建完成if(http10>0)  strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"\r\n");//zzy:以下1234个if是为了构建http请求头//zzy:请求头介绍:http://www.cnblogs.com/zcy_soft/archive/2012/03/05/2380595.htmlif(proxyhost==NULL && http10>0){strcat(request,"Host: ");strcat(request,host);strcat(request,"\r\n");}if(force_reload && proxyhost!=NULL){strcat(request,"Pragma: no-cache\r\n");}if(http10>1)strcat(request,"Connection: close\r\n");/* add empty line at end */if(http10>0) strcat(request,"\r\n"); // printf("Req=%s\n",request);
}/* vraci system rc error kod */
static int bench(void)
{//zzy:个人觉得这个ijk不太好,ijk是为了父进程以后从文件流中读出子进程所给的speed,fail和bytes而设定的int i,j,k;  pid_t pid=0;FILE *f;/*check avaibility of target server */i=Socket(proxyhost==NULL?host:proxyhost,proxyport);if(i<0) { fprintf(stderr,"\nConnect to server failed. Aborting benchmark.\n");return 1;}close(i);/*create pipe *///zzy:通信使用,就是子进程发送本分支压力测试的结果给父进程,父进程接收读结果的一个通信if(pipe(mypipe)){perror("pipe failed.");return 3;}/* 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=0;i<clients;i++){pid=fork();if(pid <= (pid_t) 0){/*child process or error*/sleep(1); /* make childs faster */break;}}if( pid< (pid_t) 0){fprintf(stderr,"problems forking worker no. %d\n",i);perror("fork failed.");return 3;}//zzy:子进程的任务如下if(pid== (pid_t) 0){/* I am a child *///zzy:有代理测代理,没有代理测一般普通的那种urlif(proxyhost==NULL)benchcore(host,proxyport,request);elsebenchcore(proxyhost,proxyport,request);/* write results to pipe */f=fdopen(mypipe[1],"w");if(f==NULL){perror("open pipe for writing failed.");return 3;}/* fprintf(stderr,"Child - %d %d\n",speed,failed); *///zzy:测试结果给父进程,然后本分支进程测试结束fprintf(f,"%d %d %d\n",speed,failed,bytes);fclose(f);return 0;} else{f=fdopen(mypipe[0],"r");if(f==NULL) {perror("open pipe for reading failed.");return 3;}setvbuf(f,NULL,_IONBF,0);speed=0;failed=0;bytes=0;while(1){/*zzy:我感觉是所有的写都写完了也就是fscanf会自动阻塞直到所有写的fp关闭它才会读,*要不然多进程对同一个流操作,不用锁,很容易数据错乱,*而且如果是实时读,那么当fscanf发现目前没有数据,*也就是本次数据没有到来,而并不意味这子进程结束,*也就是子进程可能还在recvbuf或者怎样的时候,*本次EOF fscanf意味着循环结束,*那么工作中的子进程没有办法给父进程传数据了,*但是我没有找到相关的信息.当然我的锅,我没有阅读过fscanf源码*同理,fprintf也自带阻塞,不然也会数据错乱*/pid=fscanf(f,"%d %d %d",&i,&j,&k);//出错或者到头了就if(pid<2){fprintf(stderr,"Some of our childrens died.\n");break;}//zzy:父进程作为主干,总和各分支的情况speed+=i;failed+=j;bytes+=k;/*fprintf(stderr,"*Knock* %d %d read=%d\n",speed,failed,pid); */if(--clients==0) break;}fclose(f);//zzy:打印总和信息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;
}void benchcore(const char *host,const int port,const char *req)
{int rlen;char buf[1500];int s,i;struct sigaction sa;/*setup alarm signal handler */sa.sa_handler=alarm_handler;sa.sa_flags=0;if(sigaction(SIGALRM,&sa,NULL)) exit(3);//zzy:alarm解释:https://typecodes.com/linux/linuxalarmknockfunc.htmlalarm(benchtime);rlen=strlen(req);
nexttry:while(1){//zzy:如果超时,就不给那个网站发数据了,也就是本分支的测试任务已经完成if(timerexpired){if(failed>0){/*fprintf(stderr,"Correcting failed by signal\n"); */failed--;}return;}s=Socket(host,port);                          //zzy:以下是各种发送出错情况if(s<0) { failed++;continue;}if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;}if(http10==0) if(shutdown(s,1)) { failed++;close(s);continue;}//涉及到接收http响应包if(force==0) {/*read all available data from socket */while(1){if(timerexpired) break; i=read(s,buf,1500);/*fprintf(stderr,"%d\n",i); */if(i<0) { failed++;close(s);//zzy:读失败了无所谓,进行下一次压力发送即可goto nexttry;}else if(i==0) break;//zzy:这里的bytes代表本分支一共接收到的bytes数量else bytes+=i;}}if(close(s)) {failed++;continue;}speed++;}
}

webbench1-5源码分析相关推荐

  1. webbench1.5 源码分析

    github 主页 readme原文: Web Bench is a very simple tool for benchmarking WWW or proxy servers. Uses fork ...

  2. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  3. SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

  4. SpringBoot-web开发(二): 页面和图标定制(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) 目录 一.首页 1. 源码分析 2. 访问首页测试 二.动态页面 1. 动态资源目录t ...

  5. SpringBoot-web开发(一): 静态资源的导入(源码分析)

    目录 方式一:通过WebJars 1. 什么是webjars? 2. webjars的使用 3. webjars结构 4. 解析源码 5. 测试访问 方式二:放入静态资源目录 1. 源码分析 2. 测 ...

  6. Yolov3Yolov4网络结构与源码分析

    Yolov3&Yolov4网络结构与源码分析 从2018年Yolov3年提出的两年后,在原作者声名放弃更新Yolo算法后,俄罗斯的Alexey大神扛起了Yolov4的大旗. 文章目录 论文汇总 ...

  7. ViewGroup的Touch事件分发(源码分析)

    Android中Touch事件的分发又分为View和ViewGroup的事件分发,View的touch事件分发相对比较简单,可参考 View的Touch事件分发(一.初步了解) View的Touch事 ...

  8. View的Touch事件分发(二.源码分析)

    Android中Touch事件的分发又分为View和ViewGroup的事件分发,先来看简单的View的touch事件分发. 主要分析View的dispatchTouchEvent()方法和onTou ...

  9. MyBatis原理分析之四:一次SQL查询的源码分析

    上回我们讲到Mybatis加载相关的配置文件进行初始化,这回我们讲一下一次SQL查询怎么进行的. 准备工作 Mybatis完成一次SQL查询需要使用的代码如下: Java代码   String res ...

  10. [转]slf4j + log4j原理实现及源码分析

    slf4j + log4j原理实现及源码分析 转载于:https://www.cnblogs.com/jasonzeng888/p/6051080.html

最新文章

  1. https://blog.csdn.net/blmoistawinde/article/details/84329103
  2. 为什么数据线easy糟糕
  3. 大话数据结构(十)java程序——队列
  4. 笔记-信息系统开发基础-信息系统开发模型
  5. 漫话:程序员要失业了??!机器人开始在GitHub上修Bug了。
  6. 基于matlab的人脸五官边缘检测方法,人脸边缘检测方法研究与仿真
  7. python如何循环sql语句_python sql 循环语句怎么写-问答-阿里云开发者社区-阿里云...
  8. Origin学习中文论坛及自带的learning center
  9. 小米 OJ 编程比赛 02 月常规赛 (Carryon 数数字)
  10. 计算机桌面右键新建展不开,Win10右键新建不见了怎么办?Win10电脑桌面右键新建没有了解决方法...
  11. 数字 IC 技能拓展(18)如何快速上手 FPGA 开发板呢
  12. 浙大竺可桢学院混合班计算机专业,起底黄峥毕业的浙大混合班:学霸不算牛 个个是学神...
  13. 请不要 “妖魔化” 外包
  14. 橙狮Scratch编程
  15. 苹果手机怎么在照片上添加文字_怎么给手机照片添加文字?没想到方法这么容易,1分钟就能学会...
  16. 第三方登陆--QQ登陆
  17. [附源码]Python计算机毕业设计高校社团管理系统Django(程序+LW)
  18. 飞天含雪看“网络红人”----社会浮躁下的一场闹剧
  19. zebradesginer zpl代码_老司机为您win7系统安装斑马GK888t打印机驱动的操作技巧
  20. 如何使用DEV-C++(超详细)

热门文章

  1. C# 实现飞行棋小游戏
  2. 微星主板从u盘启动linux挖矿,三星905s3g BIOS 设置U盘启动
  3. 【Linux服务器管理】1、用户与权限
  4. 3秒测试:组建一个网络,需要几个硬件设备搞定?
  5. 模拟地铁自动售票系统C语言,基于PLC的地铁自动售票机控制系统设计.doc
  6. JQuery中 JSON 兼容性问题(针对ie8)
  7. 流放者柯南自建服务器 linux,《流放者柯南》自建服务器教程一览 服务器搭建方法介绍...
  8. android type c 耳机检测,USB Type-C 的新音频标准将帮助 Android 设备去掉 3.5mm 耳机孔...
  9. 山东大学计算机学院复试名单,山东大学2012计算机学院拟录取名单。
  10. 砸蛋程序php,魔众砸金蛋抽奖系统PHP源码 v2.0.0