批处理之家's Archiver

happy886rr 发表于 2017-8-25 22:10

强劲的多线程下载器 purl.exe

[i=s] 本帖最后由 happy886rr 于 2017-8-26 08:54 编辑 [/i]

[quote]
控制台下强劲的多线程下载器,快如闪电。支持purl.ini配置文件。批量下载各类url资源链。
用法:
purl -i[配置文件.ini] -l[输出日志] -n[线程数] -r[根目录]\n\
配置文件书写格式
#############################################################################
[url]http://www.a.com/[/url][:0].[:1]
#############################################################################
[:0]=01-99
#############################################################################
[:1]=jpg,gif,png,bmp
[:2]=
[:3]=
...
其中[:0]到[:9]为URL通配符,启用[:0]后具有多线程效益,启用[:9]具有尾加速功能。这10个通配符可以是数字范围如:[:0]=1-9;也可以是字符范围,如[:1]=a-z;还可以是字符串枚举,如:[:2]=jpg,mp3,txt,doc
[/quote]
为节省论坛空间,不提供任何附件下载,源码发行。[code]/*
        THE THREAD DOWNLOAD TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0
        PURL.EXE
*/
#include   <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include <windows.h>
#include <process.h>
#include  <direct.h>
#include    <time.h>
#include    <math.h>
#include      <io.h>

#pragma comment(lib, "Ws2_32.lib")
#pragma comment (lib,"urlmon.lib")

/*************宏量定义*************/
#define SAFE_SIZE  512
#define FILE_EXIST 0

//定义配置文件
#define PURL_INI "\
#################################################################\n\
http://\n\
#################################################################\n\
[:0]=\n\
#################################################################\n\
[:1]=\n\
[:2]=\n\
[:3]=\n\
[:4]=\n\
[:5]=\n\
[:6]=\n\
[:7]=\n\
[:8]=\n\
#################################################################\n\
[:9]=\n\
#################################################################\n"

//定义帮助说明
#define HELP_INFORMATION "\
-----------------------------------------------------------------\n\
purl -i[inifile] -l[outlog] -n[threadnum] -r[rootdir]\n\
-----------------------------------------------------------------\n\
     -h Show help information\n\
     -i Set the purl inifile\n\
     -l Set the log output directory\n\
     -n Set the number of concurrent threads to download\n\
     -r Set the download root directory\n\
-----------------------------------------------------------------\n\
version 1.0"

/*************全局变量*************/
static int M[10], N[10], Z[10];
static int prointThread=0, nowsThread=0, trueDownload=0, totalCYC=1;

static char murl[SAFE_SIZE], outlog[SAFE_SIZE], inifile[SAFE_SIZE]=".\\purl.ini", mpath[SAFE_SIZE]=".\\", settingini[10][SAFE_SIZE*2], *S[10][SAFE_SIZE];

static BOOL renMARK[10];
static BOOL urlMARK=FALSE;

FILE* logfp;

//进度条容器
static const char* proGRESS="[                                                      ]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";

/*************事件变量*************/
//创建事件对象
HANDLE ghDataEvent;

/*************功能函数*************/
//切分字串
int ArgsSpliy(char* Str, int SN)
{
        int i=0;
        char* pstr=strtok(Str, " \t\n,");

        while(pstr !=NULL){
                S[SN][i]=(char*)calloc(strlen(pstr)+1, sizeof(char));
                strcpy(S[SN][i++], pstr);
                pstr=strtok(NULL, " \t\n,");
        }       
        return i;
}
//判断字母
BOOL isLetter(char* p)
{
        return (p && (('A'<=*p&&*p<='Z')||('a'<=*p&&*p<='z'))&&(*(p+1)=='\0'))?TRUE:FALSE;
}
//彩显函数
int ColorString(HANDLE handle_out, char* pstrA, char* pstrB, int colorA, int colorB, int num)
{
        SetConsoleTextAttribute(handle_out, colorA);  //项目色
        fprintf(stdout, pstrA);
        SetConsoleTextAttribute(handle_out, colorB);  //数据色
        (num<0)?fprintf(stdout, pstrB):fprintf(stdout, "%d\n", num);
        return 0;
}
//光标函数
BOOL DispyCursor(int size,bool mode)
{
        CONSOLE_CURSOR_INFO cinfo ={(DWORD)size, mode};
        return SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo);         
}
//域名IP解析
int DownloadURLtoIP(HANDLE handle_out, const char* downloadURL)
{
        WSADATA wsaData;  
        WSAStartup(MAKEWORD(2,2), &wsaData);

        char *pstr=(char*)downloadURL, *urlweb=(char*)calloc(SAFE_SIZE, sizeof(char)), *tstr=urlweb;

        while(*pstr!=':'){pstr++;}
        pstr+=3;
        while(*pstr!='/'&& *pstr!='\n' && *pstr!='\0'){
                *tstr++=*pstr++;
        }

        const char* pszUrl=(const char*)urlweb;

        if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)  
        {
                //fprintf(stdout, "Init socket faile\n");  
                return 1;  
        }
        struct hostent *pHost = gethostbyname(pszUrl);

        //释放空间
        free(urlweb);

        if (pHost == NULL)  
        {  
                WSACleanup();  
                //fprintf(stdout, "pHost == NULL \n");  
                return 1;  
        }

        //主机正式名称
        ColorString(handle_out, "[URL-HOST] ", (pHost)?pHost->h_name:"NULL", 4|8, 1|2|8, -1);
        fprintf(stdout, "\n");

        //主机别名,可以有多个
        int iIndex = 0;  
        while(pHost->h_aliases[iIndex])  
        {
                ColorString(handle_out, "[URLALIAS] ", pHost->h_aliases[iIndex], 4|8, 1|2|8, -1);
                fprintf(stdout, "\n");
                iIndex++;  
        }

        //地址字节数,IPV4是4,IPV6是6
        if(pHost->h_length==4)
        {
                ColorString(handle_out, "[IPV-TYPE] ", "IPV4\n", 4|8, 4|8, -1);
        }
        else if(pHost->h_length==6)
        {
                ColorString(handle_out, "[IPV-TYPE] ", "IPV6\n", 4|8, 4|8, -1);
        }

        iIndex = 0;
        while(pHost->h_addr_list[iIndex])  
        {
                ColorString(handle_out, "[IP-ADDRE] ", inet_ntoa(*(struct in_addr*)pHost->h_addr_list[iIndex]), 4|8, 4|2|8, -1);
                fprintf(stdout, "\n");
                iIndex++;  
        }   
        WSACleanup();
        return 0;
}
//开关解析
int OPTIND=1, OPTOPT;
char *OPTARG;
int GetOpt(int nargc, char *nargv[], char *ostr)
{
        static char* place="";
        static char* lastostr=(char *) 0;
        register char* oli;
        char* index();
        if(ostr!=lastostr){
                lastostr=ostr;
                place="";
        }
        if(!*place)
        {
                if(
                        (OPTIND>=nargc)              ||
                        (*(place=nargv[OPTIND])!='-')||
                        (!*(++place))
                ){
                        place="";
                        return(EOF);
                }
                if (*place == '-' && place[1] == 0){
                        ++OPTIND;
                        return(EOF);
                }
        }
        if ((OPTOPT=(int)*place++)==(int)':' || !(oli=strchr(ostr, OPTOPT))){
                if(!*place){++OPTIND;}
        }
       
        if (oli != NULL && *(++oli) != ':'){
                OPTARG=NULL;
                if(!*place){++OPTIND;}
        }
        else{
                if(*place){
                        OPTARG=place;
                }else if(nargc<=++OPTIND){
                        place="";
                }else{
                        OPTARG=nargv[OPTIND];
                }
                place="";
                ++OPTIND;
        }
        return(OPTOPT);
}

/*************获取配置*************/
int ReadSetting(char* pfile)
{                       
        //读取脚本文件
        FILE* fp;
        if( (fp=fopen(pfile, "r"))==NULL ){
                fprintf(stdout, "Reading settings failed!\n");
                exit(1);
        }

        int SN;
               
        //分配行容器
        char* LCache=(char*)calloc(1025, sizeof(char));
        //辅助行指针
        char* Line=NULL;

        while(!feof(fp)){

                memset(LCache, 0,  1024*sizeof(char));
                fgets(LCache, 1024, fp);

                //指针置换
                Line=LCache;
               
                //将尾部换行符注掉
                while(*Line!='\n'&& *Line!='\0'){Line++;}
                *Line='\0';
                Line=LCache;               

                //过滤行TAB缩进或前空格
                while(*Line=='\t'|| *Line==' '){Line++;}

                //过滤注释符
                if(Line[0]=='#'||strlen(Line)<=5){
                        continue;
                }

                //提取URL
                if(       
                        (!urlMARK)                    &&
                        (Line[0]=='h' ||Line[0]=='H') &&
                        (Line[1]=='t' ||Line[1]=='T') &&
                        (Line[2]=='t' ||Line[2]=='T') &&
                        (Line[3]=='p' ||Line[3]=='P') &&
                        (
                                Line[4]==':' ||
                                (
                                        (Line[4]=='s'||Line[4]=='S') &&
                                        (Line[5]==':')
                                )
                        )
                ){
                        if(strlen(Line)<10){
                                fprintf(stdout, "Please fill the url!\n");
                                exit(1);
                        }

                        strcpy(murl, Line);
                        while(*Line !='\0'){
                                if(*Line=='[' && *(Line+1)==':' && ('0'<=*(Line+2) && *(Line+2)<='9') && *(Line+3)==']'){
                                        renMARK[*(Line+2)-48]=TRUE;
                                        Line+=4;
                                }else{
                                        Line++;
                                }
                        }
                        urlMARK=TRUE;
                        continue;
       
                }else if(
                        (urlMARK)                     &&
                        (Line[0]=='[' &&Line[1]==':') &&
                        ('0'<=Line[2] &&Line[2]<='9') &&
                        (Line[3]==']' &&Line[4]=='=')
                       
                ){
                        SN=Line[2]-48;
                        if(!renMARK[SN]){continue;}

                        strcpy(settingini[SN], Line);

                        if(strchr(Line+5, ',')){
                                M[SN]=0;
                                N[SN]=ArgsSpliy(Line+5, SN)-1;

                        }else if(renMARK[SN]){

                                char *snumsrc=strtok(Line+5, " \t-"), *tmps=(snumsrc!=NULL)?strtok(NULL, " \t-"):NULL, *zp=snumsrc;

                                if(isLetter(snumsrc) && isLetter(tmps)){
                                        int exnum1=*snumsrc, exnum2=*tmps;
                                        Z[SN]=-1;
                                        M[SN]=(exnum1 <= exnum2)?(N[SN]=exnum2, exnum1):(N[SN]=exnum1, exnum2);

                                }else if(tmps!=NULL){               
                                        if(*zp=='0'){
                                                while('0'<= *zp && *zp <='9'){
                                                        Z[SN]++;
                                                        zp++;
                                                }
                                        }
                                        M[SN]=atoi(snumsrc), N[SN]=atoi(tmps);
                                        if(M[SN]>N[SN]){
                                                int exnum=M[SN];
                                                M[SN]=N[SN], N[SN]=exnum;
                                        }
                                }
                        }       
                }
        }       
        fclose(fp);
       
        //统计总循环次数
        for(int i=0; i<10; i++){totalCYC *=N[i]-M[i]+1;}
        return 0;
}

/*************下载函数*************/
UINT WINAPI FastDownload(void* ptr)
{
        //分配URL字串
        char* ptftr=(char*)calloc(16, sizeof(char));
        char* aurl =(char*)calloc(SAFE_SIZE, sizeof(char));
        char* dest =(char*)calloc(SAFE_SIZE, sizeof(char));
        char* durl =(char*)calloc(SAFE_SIZE, sizeof(char));
        char* titl =(char*)calloc(SAFE_SIZE, sizeof(char));
        durl[0]='.', durl[1]='\\';

        //接受线程传参
        int nThreadID = *((int*)ptr);
        int snum      = *((int*)ptr+1);
        int lnum      = *((int*)ptr+2);

        SetEvent(ghDataEvent);
        nowsThread++;
        if(*outlog != 0){
                //fprintf(logfp, "\nThe %dth thread start.\n", nThreadID+1);
        }

        //创建循环变量数组
        int i[10]={0}, SN;

        //创建下载状态变量
        BOOL preMARK=FALSE, nowMARK=FALSE;

        //定义URL指针
        char *purl=NULL, *surl=NULL, *pdit=NULL;
       
        //启动十层循环
        for(i[0]=snum; i[0]<=lnum; i[0]++)
        for(i[1]=M[1]; i[1]<=N[1]; i[1]++)
        for(i[2]=M[2]; i[2]<=N[2]; i[2]++)
        for(i[3]=M[3]; i[3]<=N[3]; i[3]++)
        for(i[4]=M[4]; i[4]<=N[4]; i[4]++)
        for(i[5]=M[5]; i[5]<=N[5]; i[5]++)
        for(i[6]=M[6]; i[6]<=N[6]; i[6]++)
        for(i[7]=M[7]; i[7]<=N[7]; i[7]++)
        for(i[8]=M[8]; i[8]<=N[8]; i[8]++)
        for(i[9]=M[9]; i[9]<=N[9]; i[9]++){

                   surl=murl, purl=aurl;

                while(*surl !='\0'){

                        //替换正则标签
                        if(*surl=='[' && *(surl+1)==':' && '0'<=*(surl+2) && *(surl+2)<='9' && *(surl+3)==']' && renMARK[*(surl+2)-48]){

                                SN=*(surl+2)-48;
                               
                                if(S[SN][0] !=NULL){
                                        pdit=S[SN][i[SN]];
                                }else{                       
                                        if(Z[SN] >0){
                                                sprintf(ptftr, "%%0%dd", Z[SN]);
                                                sprintf(dest, ptftr, i[SN]);

                                        }else if(Z[SN]==-1){
                                                sprintf(dest, "%c",  (char)i[SN]);

                                        }else{
                                                sprintf(dest, "%d",  i[SN]);
                                        }
                                        pdit=dest;
                                }
                               
                                while(*pdit !='\0'){
                                        *(purl++)=*(pdit++);               
                                }
                                surl+=4;
                                       
                        }else{
                                *(purl++)=*(surl++);
                        }
                }
                //置结束符
                *purl='\0';

                //显示当前下载的URL
                prointThread++;

                sprintf(titl, "[%03dT]-[%03dF] %s", nowsThread, trueDownload, aurl);
                SetConsoleTitleA(titl);

                //处理下载路径
                char* turl=strstr(aurl, "://")+3;
                char* sp=durl+2;

                //根据网址创建目录
                while(*turl != '\0'){
                        switch(*turl)
                        {
                        case '/':
                                *sp='\0';
                                if(_access(durl, FILE_EXIST) != 0){
                                        _mkdir(durl);
                                }
                                *sp='\\';
                                break;
                               
                        case ':':
                        case '*':
                        case '?':
                        case '"':
                        case '>':
                        case '<':
                        case '|':
                                *sp='@';
                                break;
                               
                        default:
                                *sp=*turl;
                                break;
                        }               
                        //指针移位
                        sp++, turl++;
                }
                //置结束符
                *sp='\0';

                //调用API下载
                URLDownloadToFileA(NULL, aurl, durl, 0, NULL);
       
                //下载状态
                nowMARK=(_access(durl, FILE_EXIST)==0)?TRUE:FALSE;

                //增速判断
                if(preMARK && !nowMARK && i[9]!=M[9]){
                        break;
                }

                //显示下载成功的文件
                if(nowMARK){
                        trueDownload++;
                        if(*outlog != 0){fprintf(logfp, "[*]%s\n", aurl);}
                }

                //下载状态更新
                preMARK=nowMARK;
        }

        //释放数组内存
        free(aurl);
        free(durl);
        free(dest);
        free(titl);
        free(ptftr);
       
        //线程结束
        nowsThread--;
        if(*outlog != 0){
                //fprintf(logfp, "\nThe %dth thread end!\n\n", nThreadID+1);
        }
        return (UINT)0;
}

/*************MAIN函数*************/
int main(int argc, char** argv)
{
        int threadNUMS=100;
        char K, *outLOG=NULL;
        while((K=GetOpt(argc,argv,"hi:n:p:l:"))!=-1)
        {
                switch(K)
                {
                case 'h':
                case 'H':
                        fprintf(stdout, HELP_INFORMATION);
                        exit(0);

                case 'i':
                case 'I':
                        if(OPTARG !=NULL){
                                strcpy(inifile, OPTARG);
                        }
                        break;

                case 'l':
                case 'L':
                        if(OPTARG !=NULL){
                                strcpy(outlog, OPTARG);
                        }
                        break;

                case 'n':
                case 'N':
                        if(OPTARG !=NULL){
                                int exnum=atoi(OPTARG);
                                threadNUMS=(0<exnum && exnum<SAFE_SIZE*4)?exnum:SAFE_SIZE*4;
                        }
                        break;

                case 'r':
                case 'R':
                        if(OPTARG !=NULL){
                                strcpy(mpath, OPTARG);
                        }
                        break;

                default:
                        fprintf(stdout, "Unknown switch '%c'\n", K);
                        exit(1);
                }
        }

        //判断配置文件是否存在
        if(access(inifile, FILE_EXIST)!=0){
                FILE* fp=fopen(inifile, "w");
                fprintf(fp, PURL_INI);
                fclose(fp);
                fprintf(stdout, "Please fill in the setting file\n");
                fprintf(stdout, HELP_INFORMATION);
                exit(1);
        }

        if(argc==1){
                //无参数则退出
                fprintf(stdout, HELP_INFORMATION);
                exit(0);
        }

        //判断根目录是否存在
        if(_access(mpath, FILE_EXIST)!=0){
                _mkdir(mpath);
        }
        if(_access(mpath, FILE_EXIST)==0){
                //切换至下载目录
                _chdir(mpath);
        }else{
                //无法创建根目录则退出
                fprintf(stdout, "Can not creat the root folder\n");
                exit(1);       
        }

        //读取purl配置文件
        ReadSetting(inifile);
        if(! urlMARK){
                fprintf(stdout, "Please fill in the download url\n");
                exit(1);
        }

        //获取控制台输出句柄
        HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);

        //线程传参数组
        int inum[3]={0};

        //判断是否使用多线程正则符[:0]
        if(! renMARK[0]){
                threadNUMS=1;
        }

        //线程数
        int nThreadCount=N[0]-M[0];
        if(nThreadCount<=0 && threadNUMS!=1){
                fprintf(stdout, "\nThe '[:0]' don't get incremental value\n");
                exit(1);
        }

        //创建时间结构体
        time_t startTIME, endTIME;
        struct tm* timeinfo;
        time(&startTIME);
        timeinfo=localtime(&startTIME);

        //计算线程分组数
        int rThreadAdd   =(int)ceil((nThreadCount + 1)*1.0/threadNUMS);
        int rThreadRange =(int)ceil((nThreadCount + 1)*1.0/(rThreadAdd?rThreadAdd:1.0));

        //是否开启日志输出
        if(*outlog != 0){
                logfp=fopen(outlog, "w");
                if(logfp == NULL){
                        fprintf(stdout, "Open log failed\n");
                        exit(1);
                }else{
                        fprintf(logfp,
                                "================================================================\n"
                                "The purl log file, Time: %s"
                                "================================================================\n\n"
                                ,asctime(timeinfo)
                        );
                        fprintf(logfp, "[Threads num]\n%d\n\n", rThreadRange);
                        fprintf(logfp, "[Root path]\n%s\n\n", mpath);
                        fprintf(logfp, "[The URL regular]\n%s\n\n", murl);
                        fprintf(logfp, "[Setting ini]\n");
                        for(int i=0; i<=9; i++){
                                if(settingini[i][0]!=0){
                                        fprintf(logfp, "%s\n", settingini[i]);
                                }
                        }
                        fprintf(logfp, "\n[Start the download time]\n%s\n", asctime(timeinfo));
                        fprintf(logfp, "[Successfully downloaded URL]\n");
                }
        }
        //隐藏光标
        DispyCursor((DWORD)25, FALSE);
        //显示目标网站IP
        DownloadURLtoIP(handle_out, murl);

        //分配线程句柄数组
        HANDLE* phaThread =(HANDLE*)calloc(rThreadRange, sizeof(HANDLE));
       
        //创建事件对象
        ghDataEvent =CreateEventA(NULL, FALSE, FALSE, NULL);
       
        //错误号
        int nErr=0;

        for(int i=0; i<rThreadRange; i++){

                inum[0]=i, inum[1]=M[0]+i*rThreadAdd, inum[2]=M[0]+i*rThreadAdd+rThreadAdd-1;
                if(inum[2]>N[0]){inum[2]=N[0];}

                phaThread[i]=(HANDLE)_beginthreadex(NULL, 0, FastDownload, &inum, 2048, NULL);

                 if(phaThread[i]==0){
                            nErr=GetLastError();
                            if(nErr==0x08){
                                        printf("\nOpen thread failed, lack of storage space!\n");
                        }else{
                                printf("\nOpen thread failed, error number%d\n", nErr);
                        }
                        break;
                }
                WaitForSingleObject(ghDataEvent, INFINITE);
        }

        //色彩代码 紫色1|4|8,红色4|8,绿色2|8,兰色1|2|8,黄色2|4|8,白色1|2|4|8;

        //显示最大线程
        ColorString(handle_out, "[MAX-THRE] ", "", 4|8, 4|8, rThreadRange);

        //显示开始时间
        ColorString(handle_out, "[STA-TIME] ", asctime(timeinfo), 4|8, 1|4|8, -1);

        //绘制进度框
        ColorString(handle_out, "[DOWNLOAD] ", (char*)proGRESS, 4|8, 2|4|8, -1);

        //绘制进度条
        int spi=0;
       
        do{
                //进度百分数
                int i=(totalCYC==0)?100:(prointThread*100/totalCYC), j=i/2;
                if(spi==j){
                        //缓解CPU占用
                        Sleep(30);
                        continue;
                }

                //显示递增进度
                while(spi<j){
                        fputc('=', stdout);
                        spi++;
                }

                //显示进度百分比
                fprintf(stdout, "%3d%%\b\b\b\b", i);

                //线程退出器
                if(prointThread==totalCYC){
                        break;
                }

        }while(nowsThread);

        //补全百分百进度
        if(prointThread==totalCYC){
                while(spi<50){
                        fputc('=', stdout);
                        spi++;
                }
                fprintf(stdout, "100%%");
        }
        fprintf(stdout, "\n");

        //显示结束时间
        time(&endTIME);
        timeinfo=localtime(&endTIME);
        ColorString(handle_out, "[END-TIME] ", asctime(timeinfo), 4|8, 1|4|8, -1);

        //显示花费时间
        ColorString(handle_out, "[USE-TIME] ", "", 4|8, 1|2|8, -1);
        fprintf(stdout, "Takes %gs\n", difftime(endTIME, startTIME));

        //颜色归位
        SetConsoleTextAttribute(handle_out, 1|2|4);//白色

        //关闭日志读写
        if(*outlog != 0){
                fprintf(logfp, "\n[End the download time]\n%s\n", asctime(timeinfo));
                fprintf(logfp, "[Download time-spending]\n%g seconds\n\n", difftime(endTIME, startTIME));
                fprintf(logfp, "[Percent of completion]\n%d%%\n\n", (prointThread==totalCYC)?100:spi*2);
                fprintf(logfp, "[Successfully downloaded files]\n%d", trueDownload);
                fclose(logfp);
        }
        return 0;
}
[/code]

freesoft00 发表于 2017-8-26 01:13

是我用错了吗?怎么不行。

https://download.mozilla.org/?product=firefox-55.0.3-SSL&os=win&lang=zh-CN
http://ftp.mozilla.org/pub/firefox/releases/55.0.3/win32/zh-CN/Firefox%20Setup%2055.0.3.exe
https://ipmsg.org/archive/ipmsg470src.zip


把这三个网址分别添加到purl.ini中,也不行。弹出错误。

happy886rr 发表于 2017-8-26 08:26

[i=s] 本帖最后由 happy886rr 于 2017-8-26 09:07 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=202465&ptid=45178]2#[/url] [i]freesoft00[/i] [/b]
代码已经修复,这是多线程批量下载器,只支持批量地址下载,比如[url]www.a01.com[/url], [url]www.a02.com[/url], [url]www.a03.com[/url]就是批量的网址,而不是说单一下载某个文件。
单独下载某个文件请使用pget。
purl的目的是针对有规律的数字递增网址,批量多线程下载,而且必须是几千、几万的批量网址才可以成功下载。线程过少的话,主程序很快就跑完了,子线程也就结束了。我把下载量调到5000,你的文件都成功下载了[:0]=0-5000
purl是针对繁重的批量下载任务定制的,个别几个小文件的下载多线程会得不偿失,小文件请使用pget。

freesoft00 发表于 2017-8-26 11:46

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=202466&ptid=45178]3#[/url] [i]happy886rr[/i] [/b]


    哦,知道了。用途不一样呀。

llh931886 发表于 2017-9-14 14:39

支持  ssh 链接的 sftp  下载吗?

CrLf 发表于 2017-10-10 00:37

请教下要怎么编译?
gcc和vs均未通过

523066680 发表于 2017-10-10 09:49

[i=s] 本帖最后由 523066680 于 2017-10-10 10:02 编辑 [/i]

[b]回复 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=203742&ptid=45178]6#[/url] [i]CrLf[/i] [/b]


    试了 MinGW GCC, 稍微改一下可以

添加 <stdbool.h>
注释掉两个 lib 的引入(改为手动)[code]#include <stdbool.h>

// #pragma comment(lib, "ws2_32.lib")
// #pragma comment (lib,"urlmon.lib")[/code]gcc purl.c -lws2_32 -lurlmon

happy886rr 发表于 2017-10-10 13:39

[i=s] 本帖最后由 happy886rr 于 2017-10-10 14:10 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=203742&ptid=45178]6#[/url] [i]CrLf[/i] [/b]
大师,好久不见。(后缀一定要改为cpp)
编译现在都已经实现一键了,请参看我之前的帖子[url]http://www.bathome.net/thread-44180-1-1.html[/url]
下载那个精简的vc++2010编译器(仅22M大小),把.cpp文件直接拖拽到VC.CMD批处理脚本上,就会自动生成exe。
别看体积小,编译功能与原版VS几乎没有差别。
   
另外我还发布过手机版的gcc编译器,可以实现代码直接编译为 安卓上可运行的二进制文件。从而实现 win、linux、安卓 各平台通吃。

netdzb 发表于 2019-6-28 13:11

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=203748&ptid=45178]8#[/url] [i]happy886rr[/i] [/b]

手机版本的编译器在哪里?

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.