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://”,哪位網友有愛好可以自己修改。