荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标 题: 一个简明的断点续传程序 guru (转寄)[转载]
发信站: 荔园晨风BBS站 (Thu Apr 25 10:25:48 2002), 转信
【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@apue.dhs.org 所发表 】
发信人: Suning (资优生+干苦力), 信区: LINUX
标 题: 一个简明的断点续传程序
发信站: 武汉白云黄鹤站 (Sat Sep 16 10:59:28 2000), 转信
一个简明的断点续传程序.
发信站: BBS 水木清华站 (Wed Apr 26 00:14:44 2000)
/* Get and Resume Elite EDition source code Ver .4 (Uh huh!)
First off, sorry about the mess and lack of error checking..
I'll clean it up later ;)
Get and Resume Elite EDition (GREED)
Copyright (C) 1999 Anoakie Turner
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For more information on the GPL, please go to:
http://www.gnu.org/copyleft/gpl.html
Contact: Anoakie Turner
Anoakie.Turner@asu.edu
13240 N. 94th Pl.
Scottsdale, AZ 85260
*/
/*
** To compile, use g++ -O -Wall -o greed greed.cpp
*/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define HTTP 1
#define FTP 2
#define CURRENT_VERSION "GREED/0.4"
#define GGR "http://www.public.asu.edu/~arturner/greed.tar.gz"
#define GGRS "http://www.public.asu.edu/~arturner/greed-source.tar.gz"
#define rollback 4096
int dlstat;
long dldots;
struct sockaddr_in address;
unsigned int dport;
time_t start, end;
struct URLstruct;
typedef struct URLstruct* URLp;
struct URLstruct
{ char server[512];
char file[512];
char name[1024];
char filename[256];
char user[64];
char pass[64];
char left[10];
char size[10];
char total[12];
char cport[5];
unsigned int port;
int protocol;
int sockfd;
struct hostent *host;
struct servent *serv;
long long lleft;
long long lsize;
long long ltotal;
FILE *fp;
bool done;
bool resume;
bool retry;
} URLst;
void Download(URLp URL);
bool ReadHTTPHeader(URLp URL);
bool ReadFTPListing(URLp URL);
bool Parse(URLp URL);
bool Connect(URLp URL);
void ReadString(char *str1, int *ind, char stopchar, int stopint, char* str2
);
void ReadString(char *str1, int &ind, char stopchar, int stopint, char* str2
)
//////////////////////////////////////
// void ReadString(char *str1, int &ind, char stopchar,
// int stopint, char* str2);
//
// Pre: Assigned (str1) && Assigned (ind) && Assigned (stopchar)
// && Assigned (stopint)
// Post: a string starting at ind and ending at (stopchar ||
// stopint) is copied int str2
//////////////////////////////////////
{ int stringIndex = 0;
for (; ind < stopint && str1[ind] != stopchar; ind++)
str2 [stringIndex++] = str1[ind];
str2 [stringIndex] = '\0';
}
bool Parse(URLp URL)
//////////////////////////////////////
// bool Parse(URLp URL);
//
// Parses a URL
//
// Pre: Assigned (URL->name)
// Post: URL->name parsed, URL->(filename, file, protocol, user, pass, cport
, seerver, port)
// set. Returns 1 if successful.
//////////////////////////////////////
{ int at = 0;
int i = 0;
dlstat = 0;
dldots = 0;
URL->retry = 0;
for(i = strlen(URL->name); i > 0 && URL->name[i] != '@'; i--);
if(URL->name[i] == '@') at = i;
if (strstr(URL->name, "http://") != NULL || strstr(URL->name, "ftp:/
/") != NULL)
{ if(URL->name[0] == 'f')
{ i = 6;
URL->protocol = FTP;
}
else
{ i = 7;
URL->protocol = HTTP;
}
if (at)
{ ReadString(URL->name, i, ':', at, URL->user);
i++,ReadString(URL->name, i, '\0', at, URL->pass);
i++;
}
else
{ strcpy(URL->user, "anonymous");
strcpy(URL->pass, "-anonuser@anonymous.com");
}
} else
{ i = 0;
if(URL->name[0] == 'f')
URL->protocol = FTP;
else
URL->protocol = HTTP;
}
at = i;
ReadString(URL->name, i, ':', strlen(URL->name), URL->server);
if (URL->name[i] != ':')
{ i = at;
ReadString(URL->name, i, '/', strlen(URL->name), URL->server
);
if (URL->protocol == FTP)
strcpy (URL->cport, "21");
else
strcpy (URL->cport, "80");
}
else
i++,ReadString(URL->name, i, '/', strlen(URL->name), URL->cp
ort)
ReadString(URL->name, i, '\0', strlen(URL->name), URL->file);
for (i = strlen(URL->name); i > 0 && URL->name[i] != '/'; i--);
i++,ReadString(URL->name, i, '\0', strlen(URL->name), URL->filename)
;
if (URL->file[0] == '\0')
{ strcpy (URL->file, "/");
strcpy (URL->filename, "index.html");
} else if (URL->file[strlen(URL->file) - 1] == '/')
strcpy (URL->filename, "index.html");
URL->port = atoi(URL->cport);
return (1);
}
bool Connect(URLp URL)
//////////////////////////////////////
//
//
//
//
//////////////////////////////////////
{ URL->host = gethostbyname(URL->server);
if (URL->host == NULL)
{ printf("Error resolving host!\n");
return(0);
}
printf("Connecting to: %s:%d\n", URL->server, URL->port);
URL->sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (URL->sockfd == -1)
{ printf("Error opening socket to server\n");
return(0);
}
address.sin_family = AF_INET;
address.sin_port = htons(URL->port);
memcpy(&address.sin_addr, URL->host->h_addr, URL->host->h_length);
if(connect(URL->sockfd, (struct sockaddr *)&address, sizeof(address)
) < 0)
{ printf("Error in connecting to server!\n");
return(0);
} else
if (URL->protocol == HTTP)
{ write(URL->sockfd, "GET ", 4);
write(URL->sockfd, URL->file, strlen(URL->file));
write(URL->sockfd, " HTTP/1.1\r\nHost: ", 17);
write(URL->sockfd, URL->server, strlen(URL->server));
write(URL->sockfd, ":", 1);
write(URL->sockfd, URL->cport, strlen(URL->cport));
write(URL->sockfd, "\r\nUser-Agent: ", 14);
write(URL->sockfd, CURRENT_VERSION, strlen(CURRENT_VERSION))
;
write(URL->sockfd, "\r\nAccept: *.*, */*\r\n", 20);
write(URL->sockfd, "Range: bytes=", 13);
} else
{ write(URL->sockfd, "USER ", 5);
write(URL->sockfd, URL->user, strlen(URL->user));
write(URL->sockfd, "\r\nPASS ", 7);
write(URL->sockfd, URL->pass, strlen(URL->pass));
write(URL->sockfd, "\r\nPASV\r\nREST 0\r\n", 16);
write(URL->sockfd, "NOOP\r\n", 6);
URL->resume = 1;
if (strstr(URL->user, "anonymous") != NULL)
write(URL->sockfd, "LIST -L ", 8);
else
write(URL->sockfd, "LIST -L ~", 9);
write(URL->sockfd, URL->file, strlen(URL->file));
write(URL->sockfd, "\r\n", 2);
}
return 1;
}
bool ReadHTTPHeader(URLp URL)
//////////////////////////////////////
// bool ReadHTTPHeader(URLp URL)
//
// URL->protcol == HTTP, HTTP header read.
//
// Pre: Assigned(URL->size) && Assigned(URL->filename) && Assigned(URL->soc
kfd)
// Post: URL->fp, URL->lsize, URL->left, and URL->lleft set. Returns 1
// if successful
//////////////////////////////////////
{ int bsize = 0;
char *temp, *fin;
char buffer[4096];
int i;
URL->done = 0;
URL->fp = fopen (URL->filename, "a+b");
URL->lsize = ftell(URL->fp);
if ((URL->lsize >= URL->ltotal) && URL->ltotal != 0)
{ printf("Error... It seems this file has already been downloa
ded..\n");
return(0);
} else
if (URL->fp == NULL)
{ printf("Error opening file %s\n", URL->filename);
return(0);
} else
if (URL->lsize == -1)
URL->lsize = 0;
sprintf(URL->size, "%lld", URL->lsize);
write(URL->sockfd, URL->size, strlen(URL->size));
write(URL->sockfd, "-\r\n\r\n", 5);
dldots = URL->lsize / rollback;
bsize = read(URL->sockfd, buffer, sizeof(buffer) - 1);
if (!(fin=strstr(buffer,"\r\n\r\n")))
{ printf("Error - webserver headers too large, fatal!\n");
return(0);
}
*fin='\0'; fin+=4;
if (strstr(buffer,"Transfer-Encoding: chunked"))
{ printf("Error - \"chunked\" Transfer-Encoding not implemente
d, II'm violating HTTP 1.1!\n");
return(0);
}
if (URL->lsize && !strstr(buffer,"Content-Range:"))
{ printf("Error - server says we already have the completed fi
le, resuming too dangerous!\n");
return(0);
}
printf("Resuming from %s bytes.\r\n", URL->size);
//NOTE: I have changed Content-Length to ength because
// people have notified me that some servers don't
// capitalize the L in length.
temp = strstr (buffer, "ength: ");
if (temp != NULL)
{ for (i = 0; temp[i + 7] != '\r'; i++)
URL->left[i] = temp[i + 7];
URL->left [i] = '\0';
URL->lleft = atol(URL->left);
if (URL->lsize == URL->lleft)
{ printf("Error... I think that you are trying to resu
me aa file that has already been downloaded!\n");
return 0;
}
printf("%s bytes left to download!\r\n", URL->left);
URL->resume = 1;
URL->lleft -= (bsize-(fin-buffer));
} else
{ printf("Error in web site file size estimation, or unknown s
erveer type\n\n");
URL->resume = 0;
URL->lleft = 2000000000;
}
fwrite(fin,bsize-(fin-buffer),1,URL->fp);
printf("[.");
fflush(NULL);
return 1;
}
bool ReadFTPListing (URLp URL)
//////////////////////////////////////
//
//
//
//////////////////////////////////////
{ int result = 1;
int len = 1;
int i = 0;
int j = 0;
int k = 0;
int listfd = 0;
int datafd = 0;
char buffer[64000], buffer2[64000], buffer3[64000], buffer4[64000];
char lhost[5][4];
char *rbuffer = NULL;
struct sockaddr_in datastream, liststream;
URL->resume = 1;
while(result > 0)
{ result = read(URL->sockfd, buffer + len - 1, sizeof(buffer)
+ leen - 1);
len += result;
if (strstr(buffer, "200") != NULL)
result = 0;
}
rbuffer = strstr(buffer, "Passive Mode (");
if (rbuffer == NULL)
{ printf("PASV mode not supported, aborting.\n");
exit(0);
} else
for (i = 14; (unsigned)i < strlen(rbuffer) && rbuffer[i] != ')'; i++
)
if (rbuffer[i] == ',')
{ lhost[j][k] = '\0';
j++;
k = 0;
} else
lhost[j][k++] = rbuffer[i];
listfd = socket(AF_INET, SOCK_STREAM, 0);
if (listfd == -1)
{ printf("Error opening socket to FTP server for LIST!\n");
return(0);
}
liststream.sin_family = AF_INET;
liststream.sin_port = htons(atoi(lhost[4])*256 + atoi(lhost[5]));
memcpy(&liststream.sin_addr, URL->host->h_addr, URL->host->h_length)
;
if (connect(listfd, (struct sockaddr *)&liststream, sizeof(liststrea
m)) == -1)
{ printf("Error connecting to FTP socket for LIST!\n");
close(listfd);
URL->retry = 1;
return(0);
}
result = 1;
len = 1;
while(result > 0)
{ result = read(listfd, buffer2 + len - 1, sizeof(buffer2) + l
en -- 1);
len += result;
}
int whitespace = 0;
for (j = 0; (unsigned)j < strlen(buffer2) && whitespace < 4; j++)
{ if (buffer2[j] == ' ' && buffer2[j + 1] != ' ')
whitespace ++;
}
for (k = 0; (unsigned)j < strlen(buffer2); j++)
if (buffer2[j] == ' ' || (buffer2[j] > ('0' - 1) && buffer2[
j] << ('9' + 1)))
URL->total[k++] = buffer2[j];
else
j = strlen(buffer2);
URL->total[j - 4] = '\0';
URL->ltotal = atol(URL->total);
printf("File size: %lld bytes\n", URL->ltotal);
close(listfd);
write(URL->sockfd, "PASV\r\n", 6);
write(URL->sockfd, "REST 0\r\n", 8);
write(URL->sockfd, "NOOP\r\n", 6);
result = 1;
len = 1;
while(result > 0)
{ result = read(URL->sockfd, buffer3 + len - 1, sizeof(buffer3
) + len - 1);
len += result;
if (strstr(buffer3, "200") != NULL)
result = 0;
}
rbuffer = strstr(buffer3, "Passive Mode (");
if (rbuffer == NULL)
return(0);
else
for (i = 14, j = 0, k = 0; (unsigned)i < strlen(rbuffer) &&
rbufffer[i] != ')'; i++)
if (rbuffer[i] == ',')
{ lhost[j][k] = '\0';
j++;
k = 0;
}
else
lhost[j][k++] = rbuffer[i];
URL->fp = fopen (URL->filename, "a+b");
URL->lsize = ftell(URL->fp);
if (URL->lsize >= URL->ltotal)
{ printf("Error... It seems this file has already been downloa
ded..\n");
return(0);
} else
if (URL->fp == NULL)
{ printf("Error opening file %s\n", URL->filename);
return(0);
} else
if (URL->lsize < rollback)
URL->lsize = 0;
else
URL->lsize -= rollback;
ftruncate(fileno(URL->fp), URL->lsize);
sprintf(URL->size, "%lld", URL->lsize);
printf("Resuming from %s bytes.\n\n", URL->size);
write(URL->sockfd, "TYPE I\r\n", 8);
write(URL->sockfd, "REST ", 5);
write(URL->sockfd, URL->size, strlen(URL->size));
write(URL->sockfd, "\r\n", 2);
dldots = (long long)URL->lsize / rollback;
write(URL->sockfd, "RETR ", 5);
write(URL->sockfd, URL->file, strlen(URL->file));
write(URL->sockfd, "\r\n", 2);
datafd = socket(AF_INET, SOCK_STREAM, 0);
if (datafd == -1)
{ printf("Error opening socket to FTP server for RETR!\n");
URL->retry = 1;
return(0);
}
datastream.sin_family = AF_INET;
datastream.sin_port = htons(atoi(lhost[4])*256 + atoi(lhost[5]));
memcpy(&datastream.sin_addr, URL->host->h_addr, URL->host->h_length)
;
if (connect(datafd, (struct sockaddr *)&datastream, sizeof(datastrea
m)) == -1)
{ printf("Error connecting to FTP socket for RETR!\n");
close(datafd);
URL->retry = 1;
return(0);
}
result = 1; len = 1;
while(result > 0)
{ result = read(URL->sockfd, buffer4 + len - 1, sizeof(buffer4
) + len - 1);
len += result;
if (strstr(buffer4, "350") != NULL)
result = 0;
}
listfd = URL->sockfd;
URL->sockfd = datafd;
close (listfd);
URL->lleft = URL->ltotal - URL->lsize;
printf("[.");
return (1);
}
void Download(URLp URL)
//////////////////////////////////////
// void Download(URLp URL)
//
// Downloads up to 4k of data from URL->sockfd and writes it to URL->fp
//
// Pre: Assigned(URL->sockfd) && Assigned(URL->lleft) && Assigned(URL->fp)
&& UURL->done != 1
// Post: set URL->done = 1, if finished.
//////////////////////////////////////
{ int bsize = 1;
char buff[rollback];
bsize = read(URL->sockfd, buff, sizeof(buff));
URL->lleft = URL->lleft - bsize;
if (bsize > 0)
dlstat += bsize;
fwrite(buff, bsize, 1, URL->fp);
if (dlstat > rollback - 1)
{ printf(".");
dlstat -= rollback;
fflush(NULL);
dldots ++;
if (dldots%50 == 0)
{ printf("] -%ldk %.2fk/sec- \n[.", (rollback * dldot
s) // 1024,
((float)((rollback * 50) / 1024))
/ ((float)(time((time_t *)0) - start)));
start = time((time_t *)0);
}
}
if ((bsize < 1) || (URL->lleft < 1 && URL->resume))
{ if (dldots%50 == 0)
printf("] -%ldk %.2fk/sec-\n\nChecking Completion St
atuss...\n",
(rollback * dldots)/1024,
((float)((rollback * 1) / 1024)) /
((float)(time((time_t *)0) - start)));
else
printf("] -%ldk %.2fk/sec-\n\nChecking Completion St
atuss...\n",
(rollback * dldots)/1024,
((float)((rollback * (dldots%50)) / 1024)) /
((float)(time((time_t *)0) - start)));
close(URL->sockfd);
fclose(URL->fp);
URL->done = 1;
printf("%s Done!\n\n", URL->filename);
}
}
int main (int argc, char *argv[])
//////////////////////////////////////
//
//
//
//
//////////////////////////////////////
{ URLp URL = &URLst;
int i;
printf("%s [Get and Resume Elite EDition] - By Anoakie Turner\r\n",
CURRRENT_VERSION);
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
{ if (argv[i][1] == 'n' || argv[i][1] == 'N')
{ argv[i] = GGR;
} else
{ printf("\n\nUSEAGE: greed URL(1) URL(2) ...
URL((N)\n");
printf("i.e.: greed %s ftp://some.where/out/
therre.tar.gz\n", GGR);
exit(0);
}
}
for (i = 1; i < argc; i ++)
{ strcpy(URL->name, argv[i]);
if (Parse(URL))
if (Connect(URL))
if ((URL->protocol == HTTP && ReadHTTPHeader(URL)) ||
(URL->protocol == FTP && ReadFTPListing(URL)))
{ start = time((time_t *)0);
while (!URL->done)
Download(URL);
}
close (URL->sockfd);
if (URL->retry == 1)
{ URL->retry = 0;
i--;
printf("Retrying in 5 seconds...\n");
sleep(5);
}
}
return(EXIT_SUCCESS);
}
--
--
※ 转寄:·UNIX编程 apue.dhs.org·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店