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);