C.前面看了一大段是不是有点云里雾里的啊?是有点罗嗦,但是俗话说:“万事总是开头难”OK,现在总算可以写主程序文件了。 下面就是ant.c文件 #include "ant.h" #include "signal.h"
//0表示不用,1表示用代理 int use_proxy; //代理服务器的地址 char proxy_server[100]; //端口 u_short proxy_port; //蚂蚁数目 int ant_num; //下载量 int bulk; //下载进程 int progress; char cfgfile[256]; char logfile[256]; strUCt Ant* ants[10]; struct Mission ms; //响应异常退出,将url、ant数据结构中的变量值,存放到log文件。 void justpause() { int i; FILE* log; log=fopen(logfile,"w"); fprintf(log,"%s ",ms.url); for(i=0;iamount!=0) fprintf(log, "%d:%d ",ants[i]->position,ants[i]->amount); fclose(log); exit(1); } //总算挨到主程序了,呵呵。。。。。 int main(int argc,char** argv) { int n; int maxfd; char savefile[256]; FILE* goods; FILE* log; fd_set rset,aset; int finished; int length; char status[80]; char c; struct sigaction sa; //初始化环境参数 init_env( ); //对命令行传进来的参数做判定 while((c=getopt(argc,argv,"n:u:s:p:l:h"))!=EOF){ switch (c){ //取得蚂蚁数目 case 'n': ant_num=atoi(optarg); if(ant_num > MAXANTNUM) ant_num = MAXANTNUM; break; //取得目标的url地址。 case 'u': strcpy(ms.url, optarg); break; //取得代理的地址 case 's': strcpy(proxy_server, optarg); use_proxy=1; break; //取得代理的端口 case 'p': use_proxy=1; proxy_port=(u_short)atoi(optarg); break; //取得日志文件名 case 'l': strcpy(logfile,optarg); break; case 'h': printf("usage: ant -n antnum -u url -s proxyserver -p prxoy_port -l logfile "); return 1; } } //从日志文件中读取url if(logfile[0] != 0){ log = fopen(logfile, "r+"); strcpy(ms.url,get_url_from_log(log)); } //将值赋代理服务器的相关变量 if(use_proxy){ strcpy(ms.host,proxy_server); ms.port=proxy_port; }else{ strcpy(ms.host, extract_from_url(ms.url, SITENAME)); ms.port = atoi(extract_from_url(ms.url, PORTNAME)); } //假如有下载日志,从日志中取相关信息 if(logfile[0] != 0){ printf("The file you havent download,continue......."); n=0; strcpy(ms.url,get_url_from_log(log)); while (1) { ants[n] = (struct Ant*)malloc(sizeof(struct Ant)); memset(ants[n], 0, sizeof(struct Ant)); if(!(assign_mission(log, ants[n]))) break; n++; if(n > MAXANTNUM){ printf("You logfile must be wrong! "); exit(1); } } fclose(log); free(ants[n]); ant_num=n; } else{ //取得下载文件的大小,为每只蚂蚁分配下载位置。
bulk=get_size_of_url(&ms); if(bulk==0){ printf("Cannot get the size of this object! "); ant_num=1; ants[0] = (struct Ant*)malloc(sizeof(struct Ant)); ants[0]->position=0; ants[0]->amount=1073741823; } else if(bulk==-1){ printf("Cannot connect to the site! "); exit(1); } else{ for(n=0; nposition = (bulk/ant_num)*n; if(n!=(ant_num-1)) ants[n]->amount = bulk/ant_num; else ants[n]->amount = bulk-(bulk/ant_num)*(ant_num-1); } } } //} maxfd=0; //重设&rset FD_ZERO(&rset); //下载,按蚂蚁数开线程 for(n=0; nants[n]->s?maxfd:ants[n]->s; } } if(!maxfd){ printf("no ant go work! "); return 1; } memset(&sa,0,sizeof(struct sigaction)); //打开存储文件 strcpy(savefile, extract_from_url(ms.url, FILENAME)); if(!(goods=fopen(savefile, "r+"))){ if(!(goods=fopen(savefile,"w"))){ printf("Can not open file to save . "); exit(1); } } strcpy(logfile, savefile); strcat(logfile, ".log"); //处理进程改变 sa.sa_handler=justpause; sa.sa_flags=SA_ONESHOT; sigaction(SIGINT, &sa, NULL); maxfd++; finished = 0; progress = 0; printf(" "); printf("Downloading ....................now! "); while(1){ if(finished==ant_num){ break; } aset=rset; select(maxfd,&aset,NULL,NULL,NULL); for(n=0;ns,&aset)){ if(!(length=receive(ants[n], goods))){ unenroll(ants[n], &rset); finished++; } } } } unlink(logfile); log=(FILE*)NULL; //打开日志文件 if(ant_num!=1){ for(n=0;namount){ if(!log){ log=fopen(logfile, "w+"); fputs(ms.url, log); fputc(' ',log); } //保存状态 save_status(ants[n], log); printf("Ant %d have not done!%d ",n+1,ants[n]->amount); } else printf("Ant %d done! ", n+1); free(ants[n]); } } else free(ants[0]); fclose(goods); if(log) fclose(log); return 1; } D.写完程序下面就是做makefile.程序比较小,所以MAKEFILE也比较简单: CC = gcc CFLAGS = source=ant.h ant.c funcs.c object=ant.o funcs.o ant:$(object) $(CC) $(object) -o $@ %o:%c $(CC) -c $< -o $@ $(CFLAGS) bak: tar czvf ant.tgz Makefile $(source) rm -f $(object) OK.到这总算飞到目的地了。现在你只要在命令行下用“make”命令就可以编译了。 4。教训 有一个错误,调了很久才发现,就是当fprintf(log,"%s ",ms.url)这样的语句的指针变量为空时,程序执行过程中就会发生“Segmentation fault (core dumped)”这样的错误。另外,由于程序没有多加判定,在输入url时,千万要带上“http://”或“FTP://”,哪位网友有爱好可以自己修改。
|