分享
 
 
 

对上述png服务器性能测试的程序

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

一、程序说明:

本程序对上述png服务器性能进行测试。(开发于FreeBSD,并可编译运行于Windows Cygwin环境)。

二、使用说明:(类似于ab)

st [options] [http://]hostname/path

-n requests Number of requests to perform

-c concurrency Number of multiple requests to make

-v Print version number and exit

-h Display usage information (this message)

三、源代码:

/******************************************************************************

* Copyright (C) 2004-2005 XiongBin Xiong All rights reserved

* References: Stevens,W.R. 1992. Advanced Programming in the UNIX Environment.

* Addison-Wesley.

* Stevens,W.R. 1998. UNIX Network Programming Volum1.

* Prentice Hall PTR.

*/

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/stat.h>

#include <sys/time.h>

#include <netinet/in.h>

#include <fcntl.h>

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <netdb.h>

#include <signal.h>

#define BUFFSIZE 65535

#define MAXLINE 4096

static int requests=1; /* 在测试会话中所执行的请求个数,默认为一个 */

static int concurrency=1; /* 并发级别,一次产生的请求个数,默认是一次一个 */

static int done; /* 在测试会话中所完成的请求个数 */

static int recvdatas=0; /* 接收的总数据量 */

static char *hostname,*pathname; /* 主机名、请求路径名 */

static struct timeval take_time; /* 完成所有请求所需的时间 */

static int lflag; /* 子进程结束计数标志 */

int parse_url(char *); /* 将URL分解为hostname和pathname */

int test(void); /* 开始进行测试 */

int con_test(int); /* 并发进程测试 */

int fork_do(void); /* 测试程序 */

int record(int); /* 记录测试数据 */

int lock_reg(int,int,int,off_t,int,off_t); /* 使用记录锁对共享文件进行保护 */

static void output_results(void); /* 输出结果 */

static void sig_chld(int); /* 处理子进程SIGCHLD信号 */

static void usage(const char *); /* 提示信息 */

static void err(char *); /* 出错处理函数 */

static void copyright(void); /* 版本信息 */

int

main(int argc, char *argv[])

{

int flag;

char *url;

FILE *fp;

if(argc<2||argc>6){

printf("Invalid input\n");

usage(argv[0]);

exit(1);

}

opterr=0;

while((flag=getopt(argc,argv,"n:c:hv"))!=EOF){

switch(flag){

case 'n':

requests=atoi(optarg); /* 总请求数 */

if(requests<=0)

err("Invalid number of requests");

break;

case 'c':

concurrency=atoi(optarg); /* 并发请求的级别,即每个并发请求中同时发起的请求数 */

if(concurrency<=0)

err("Invalid number of concurrency");

break;

case 'h':

usage(argv[0]); /* 帮助信息 */

break;

case 'v':

copyright(); /* 版本信息 */

exit(0);

case '?':

printf("unrecognized option: -%c\n",optopt); /* 错误的参数 */

usage(argv[0]);

exit(1);

}

}

if(requests<concurrency) /* 并发级别要小于总请求数 */

err("Invalid number of requests or concurrency");

done=requests;

fp=fopen("temp.log","wb");

fprintf(fp,"%d\t%d",done,recvdatas); /* 设置文件初值 */

fclose(fp);

if(optind>=argc)

err("Invalid input");

else

url=argv[optind];

if(parse_url(url)) /* 将URL分解为hostname和pathname */

err("Invalid URL address");

copyright();

write(STDOUT_FILENO,"testing...",10);

test(); /* 开始进行测试 */

output_results(); /* 结果输出 */

unlink("temp.log"); /* 删除临时文件 */

exit(0);

}

/*----------------------------------------------------------------*/

/* 将URL分解为hostname和pathname */

int

parse_url(char *url)

{

char *p,*pp,*urlptr;

urlptr=url;

if(strncmp(urlptr,"http://",7)==0) /* 寻找"http://"处 */

urlptr=urlptr+7;

if((p=strstr(urlptr,"\n"))!=0) /* 寻找"\n"处 */

*p='\0';

p=strchr(urlptr,'/'); /* 寻找'/'处 */

if(p==0)

return(1);

pathname=p+1; /* 获取pathname */

*p='\0';

hostname=urlptr; /* 获取hostname */

return(0);

}

/*-----------------------------------------------------------------*/

/* 开始进行测试 */

int

test(void)

{

int i,n,m;

struct timeval start_time,end_time;

n=requests/concurrency; /* n为并发循环次数 */

m=requests%concurrency; /* 当上面不能整除时,m为最后一次并发请求的并发级别 */

gettimeofday(&start_time,NULL); /* 获取测试开始时间 */

for(i=0;i<n;i++){

con_test(concurrency); /* 并发测试 */

}

con_test(m); /* 剩余并发测试 */

gettimeofday(&end_time,NULL); /* 获取测试结束时间 */

if(end_time.tv_usec<start_time.tv_usec){

take_time.tv_usec=end_time.tv_usec+1000000-start_time.tv_usec;

end_time.tv_sec--;

}else

take_time.tv_usec=end_time.tv_usec-start_time.tv_usec;

take_time.tv_sec=end_time.tv_sec-start_time.tv_sec; /* 测试总耗时 */

return;

}

/*-----------------------------------------------------------------*/

/* 并发进程测试 */

int

con_test(int level)

{

int i,pid;

lflag=level;

signal(SIGCHLD,sig_chld); /* 获取SIGCHLD信号 */

for(i=0;i<level;i++){

if((pid=fork())<0){

printf("con_test(): fork error,\trefork\n");

i--;

}

else if(pid==0){ /* 生成并发子进程 */

fork_do(); /* 测试 */

exit(0);

}

}

while(lflag); /* 等待所有并发子进程结束 */

return(0);

}

/*------------------------------------------------------------------*/

/* 测试程序 */

int

fork_do(void)

{

int i,n,l,k,pid,ppid;

struct sockaddr_in servaddr;

char buf[BUFFSIZE],pngname[MAXLINE],cpid[8],*p,*h,rbuf[MAXLINE]="GET /";

FILE *ffp;

int sockfd;

struct hostent *hp;

struct in_addr **ptr;

hp=gethostbyname(hostname); /* 获取IP地址 */

ptr=(struct in_addr **)hp->h_addr_list;

sockfd=socket(AF_INET,SOCK_STREAM,0);

bzero(&servaddr,sizeof(servaddr)); /* 初始化套接口地址结构 */

servaddr.sin_family=AF_INET;

servaddr.sin_port=htons(80);

memcpy(&servaddr.sin_addr,*ptr,sizeof(struct in_addr));

l=0;

if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0)

printf("connect error\n");

else{ /* 连接成功 */

strcat(rbuf,pathname);

strcat(rbuf," HTTP/1.0"); /* 形成GET请求命令 */

n=strlen(rbuf);

if(write(sockfd,rbuf,n)!=n) /* 发送GET请求至服务器 */

err("fork_do(): write error");

l=recv(sockfd,buf,sizeof(buf),0); /* 接收服务器返回数据 */

if((pid=getpid())<0)

err("fork_do(): getpid error");

sprintf(cpid,"%d",pid);

strcpy(pngname,"clipng");

strcat(pngname,cpid);

strcat(pngname,".png"); /* 形成带有PID的文件名 */

ffp=fopen(pngname,"wb"); /* 创建文件 */

unlink(pngname);

p=strstr(buf,"\n\n");

h=buf;

k=p-h+2; /* 定位在PNG数据区开始处 */

fwrite(&buf[k],sizeof(char),l-k,ffp); /* 写入数据 */

}

record(l); /* 记录本次请求的数据 */

close(sockfd);

fclose(ffp);

return(0);

}

/*------------------------------------------------------------------*/

/* 记录测试数据 */

int

record(int recvn)

{

int fd,a,b;

FILE *fp;

if((fp=fopen("temp.log","r+"))==NULL) /* 读写方式打开文件 */

return(1);

fd=fileno(fp);

while((lock_reg(fd,F_SETLK,F_WRLCK,0,SEEK_SET,0))==-1); /* 给文件加锁 */

fscanf(fp,"%d\t%d",&a,&b); /* 从文件得到当前数据 */

if(recvn)

b+=recvn; /* 如果connect成功,接收数据量累加 */

else

a--; /* connect失败,完成次数减一 */

rewind(fp);

fprintf(fp,"%d\t%d",a,b); /* 写入文件 */

lock_reg(fd,F_SETLK,F_UNLCK,0,SEEK_SET,0); /* 解锁 */

fclose(fp);

return(0);

}

/*-------------------------------------------------------------------*/

/* 使用记录锁对共享文件进行保护 */

int

lock_reg(int fd,int cmd,int type,off_t offset,int whence,off_t len)

{

struct flock lock;

lock.l_type=type; /* F_RDLCK,F_WRLCK,F_UNLCK */

lock.l_start=offset; /* byte offset, 起始处的相对偏移量 */

lock.l_whence=whence; /* SEEK_SET,SEEK_CUR,SEEK_END */

lock.l_len=len; /* 区域的长度(为0表示到最大位置为止) */

return(fcntl(fd,cmd,&lock)); /* 使用记录锁 */

}

/*--------------------------------------------------------------------*/

/* 输出结果 */

static void

output_results(void)

{

float takentime;

FILE *fp;

fp=fopen("temp.log","r");

fscanf(fp,"%d\t%d",&done,&recvdatas); /* 从文件中获取数据 */

takentime=((float)take_time.tv_sec)+((float)take_time.tv_usec)/1000000.0F; /* 格式化为整数+小数形式 */

printf("\n\n");

printf("Server Hostname: %s\n",hostname); /* 主机名 */

printf("Server Port: %hd\n",80); /* 端口 */

printf("Document Path: /%s\n",pathname); /* 请求路径名 */

printf("\n");

printf("Total Requests: %d\n",requests); /* 请求数 */

printf("Concurrency Level: %d\n",concurrency); /* 并发数 */

printf("Time taken for tests: %ld.%03ld seconds\n",take_time.tv_sec,take_time.tv_usec); /* 总耗时 */

printf("Complete requests: %ld\n",done); /* 完成请求数 */

printf("Failed requests: %ld\n",(requests-done)); /* 失败请求数 */

printf("Total transferred: %ld Bytes\n",recvdatas); /* 总接收数据量 */

printf("\n");

if(takentime){

printf("Requests per second: %.2f [#/sec] (mean)\n",(float)(done/takentime)); /* 每秒完成请求数 */

printf("Time per request: %.3f [ms] (mean)\n",(float)(1000*concurrency*takentime/done));/* 完成一个并发请求的时间 */

printf("Time per request: %.3f [ms] (mean, across all concurrent requests)\n",(float)(1000*takentime/done)); /* 完成一个请求的时间 */

printf("Transfer rate: %.2f [Kbytes/sec] received\n",(float)(recvdatas/takentime/1024)); /* 每秒传输数据量 */

}

printf("\n");

}

/*---------------------------------------------------------------------*/

/* 处理子进程SIGCHLD信号 */

static void

sig_chld(int signo)

{

pid_t pid;

int stat;

while((pid=waitpid(-1,&stat,1))>0) /* 处理已结束子进程状态,防止子进程Zombie状态出现 */

lflag--; /* 标志减一 */

return;

}

/*---------------------------------------------------------------------*/

/* 提示信息 */

static void

usage(const char *progname)

{

fprintf(stderr, "Usage: %s [options] [http://]hostname/path\n", progname);

fprintf(stderr, "Options are:\n");

fprintf(stderr, " -n requests Number of requests to perform\n");

fprintf(stderr, " -c concurrency Number of multiple requests to make\n");

fprintf(stderr, " -v Print version number and exit\n");

fprintf(stderr, " -h Display usage information (this message)\n");

exit(0);

}

/*----------------------------------------------------------------------*/

/* 出错处理函数 */

static void

err(char *s)

{

fprintf(stderr, "%s\n", s);

exit(1);

}

/*----------------------------------------------------------------------*/

/* 版本信息 */

static void

copyright(void)

{

printf("This is ServerTest for my pngserver, Version 1.0\n");

printf("Copyright (C) 2004-2005 XiongBin Xiong All rights reserved\n");

printf("hustxxb@hotmail.comn");

printf("\n");

}

/* end all */

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有