找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 21480|回复: 8

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

[复制链接]
发表于 2017-8-25 22:10:36 | 显示全部楼层 |阅读模式
本帖最后由 happy886rr 于 2017-8-26 08:54 编辑
控制台下强劲的多线程下载器,快如闪电。支持purl.ini配置文件。批量下载各类url资源链。
用法:
purl -i[配置文件.ini] -l[输出日志] -n[线程数] -r[根目录]\n\
配置文件书写格式
#############################################################################
http://www.a.com/[: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

为节省论坛空间,不提供任何附件下载,源码发行。
  1. /*
  2.         THE THREAD DOWNLOAD TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0
  3.         PURL.EXE
  4. */
  5. #include   <stdio.h>
  6. #include  <stdlib.h>
  7. #include  <string.h>
  8. #include <windows.h>
  9. #include <process.h>
  10. #include  <direct.h>
  11. #include    <time.h>
  12. #include    <math.h>
  13. #include      <io.h>

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

  16. /*************宏量定义*************/
  17. #define SAFE_SIZE  512
  18. #define FILE_EXIST 0

  19. //定义配置文件
  20. #define PURL_INI "\
  21. #################################################################\n\
  22. http://\n\
  23. #################################################################\n\
  24. [:0]=\n\
  25. #################################################################\n\
  26. [:1]=\n\
  27. [:2]=\n\
  28. [:3]=\n\
  29. [:4]=\n\
  30. [:5]=\n\
  31. [:6]=\n\
  32. [:7]=\n\
  33. [:8]=\n\
  34. #################################################################\n\
  35. [:9]=\n\
  36. #################################################################\n"

  37. //定义帮助说明
  38. #define HELP_INFORMATION "\
  39. -----------------------------------------------------------------\n\
  40. purl -i[inifile] -l[outlog] -n[threadnum] -r[rootdir]\n\
  41. -----------------------------------------------------------------\n\
  42.      -h Show help information\n\
  43.      -i Set the purl inifile\n\
  44.      -l Set the log output directory\n\
  45.      -n Set the number of concurrent threads to download\n\
  46.      -r Set the download root directory\n\
  47. -----------------------------------------------------------------\n\
  48. version 1.0"

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

  52. 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];

  53. static BOOL renMARK[10];
  54. static BOOL urlMARK=FALSE;

  55. FILE* logfp;

  56. //进度条容器
  57. 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";

  58. /*************事件变量*************/
  59. //创建事件对象
  60. HANDLE ghDataEvent;

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

  67.         while(pstr !=NULL){
  68.                 S[SN][i]=(char*)calloc(strlen(pstr)+1, sizeof(char));
  69.                 strcpy(S[SN][i++], pstr);
  70.                 pstr=strtok(NULL, " \t\n,");
  71.         }       
  72.         return i;
  73. }
  74. //判断字母
  75. BOOL isLetter(char* p)
  76. {
  77.         return (p && (('A'<=*p&&*p<='Z')||('a'<=*p&&*p<='z'))&&(*(p+1)=='\0'))?TRUE:FALSE;
  78. }
  79. //彩显函数
  80. int ColorString(HANDLE handle_out, char* pstrA, char* pstrB, int colorA, int colorB, int num)
  81. {
  82.         SetConsoleTextAttribute(handle_out, colorA);  //项目色
  83.         fprintf(stdout, pstrA);
  84.         SetConsoleTextAttribute(handle_out, colorB);  //数据色
  85.         (num<0)?fprintf(stdout, pstrB):fprintf(stdout, "%d\n", num);
  86.         return 0;
  87. }
  88. //光标函数
  89. BOOL DispyCursor(int size,bool mode)
  90. {
  91.         CONSOLE_CURSOR_INFO cinfo ={(DWORD)size, mode};
  92.         return SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo);         
  93. }
  94. //域名IP解析
  95. int DownloadURLtoIP(HANDLE handle_out, const char* downloadURL)
  96. {
  97.         WSADATA wsaData;  
  98.         WSAStartup(MAKEWORD(2,2), &wsaData);

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

  100.         while(*pstr!=':'){pstr++;}
  101.         pstr+=3;
  102.         while(*pstr!='/'&& *pstr!='\n' && *pstr!='\0'){
  103.                 *tstr++=*pstr++;
  104.         }

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

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

  112.         //释放空间
  113.         free(urlweb);

  114.         if (pHost == NULL)  
  115.         {  
  116.                 WSACleanup();  
  117.                 //fprintf(stdout, "pHost == NULL \n");  
  118.                 return 1;  
  119.         }

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

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

  131.         //地址字节数,IPV4是4,IPV6是6
  132.         if(pHost->h_length==4)
  133.         {
  134.                 ColorString(handle_out, "[IPV-TYPE] ", "IPV4\n", 4|8, 4|8, -1);
  135.         }
  136.         else if(pHost->h_length==6)
  137.         {
  138.                 ColorString(handle_out, "[IPV-TYPE] ", "IPV6\n", 4|8, 4|8, -1);
  139.         }

  140.         iIndex = 0;
  141.         while(pHost->h_addr_list[iIndex])  
  142.         {
  143.                 ColorString(handle_out, "[IP-ADDRE] ", inet_ntoa(*(struct in_addr*)pHost->h_addr_list[iIndex]), 4|8, 4|2|8, -1);
  144.                 fprintf(stdout, "\n");
  145.                 iIndex++;  
  146.         }   
  147.         WSACleanup();
  148.         return 0;
  149. }
  150. //开关解析
  151. int OPTIND=1, OPTOPT;
  152. char *OPTARG;
  153. int GetOpt(int nargc, char *nargv[], char *ostr)
  154. {
  155.         static char* place="";
  156.         static char* lastostr=(char *) 0;
  157.         register char* oli;
  158.         char* index();
  159.         if(ostr!=lastostr){
  160.                 lastostr=ostr;
  161.                 place="";
  162.         }
  163.         if(!*place)
  164.         {
  165.                 if(
  166.                         (OPTIND>=nargc)              ||
  167.                         (*(place=nargv[OPTIND])!='-')||
  168.                         (!*(++place))
  169.                 ){
  170.                         place="";
  171.                         return(EOF);
  172.                 }
  173.                 if (*place == '-' && place[1] == 0){
  174.                         ++OPTIND;
  175.                         return(EOF);
  176.                 }
  177.         }
  178.         if ((OPTOPT=(int)*place++)==(int)':' || !(oli=strchr(ostr, OPTOPT))){
  179.                 if(!*place){++OPTIND;}
  180.         }
  181.        
  182.         if (oli != NULL && *(++oli) != ':'){
  183.                 OPTARG=NULL;
  184.                 if(!*place){++OPTIND;}
  185.         }
  186.         else{
  187.                 if(*place){
  188.                         OPTARG=place;
  189.                 }else if(nargc<=++OPTIND){
  190.                         place="";
  191.                 }else{
  192.                         OPTARG=nargv[OPTIND];
  193.                 }
  194.                 place="";
  195.                 ++OPTIND;
  196.         }
  197.         return(OPTOPT);
  198. }

  199. /*************获取配置*************/
  200. int ReadSetting(char* pfile)
  201. {                       
  202.         //读取脚本文件
  203.         FILE* fp;
  204.         if( (fp=fopen(pfile, "r"))==NULL ){
  205.                 fprintf(stdout, "Reading settings failed!\n");
  206.                 exit(1);
  207.         }

  208.         int SN;
  209.                
  210.         //分配行容器
  211.         char* LCache=(char*)calloc(1025, sizeof(char));
  212.         //辅助行指针
  213.         char* Line=NULL;

  214.         while(!feof(fp)){

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

  217.                 //指针置换
  218.                 Line=LCache;
  219.                
  220.                 //将尾部换行符注掉
  221.                 while(*Line!='\n'&& *Line!='\0'){Line++;}
  222.                 *Line='\0';
  223.                 Line=LCache;               

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

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

  230.                 //提取URL
  231.                 if(       
  232.                         (!urlMARK)                    &&
  233.                         (Line[0]=='h' ||Line[0]=='H') &&
  234.                         (Line[1]=='t' ||Line[1]=='T') &&
  235.                         (Line[2]=='t' ||Line[2]=='T') &&
  236.                         (Line[3]=='p' ||Line[3]=='P') &&
  237.                         (
  238.                                 Line[4]==':' ||
  239.                                 (
  240.                                         (Line[4]=='s'||Line[4]=='S') &&
  241.                                         (Line[5]==':')
  242.                                 )
  243.                         )
  244.                 ){
  245.                         if(strlen(Line)<10){
  246.                                 fprintf(stdout, "Please fill the url!\n");
  247.                                 exit(1);
  248.                         }

  249.                         strcpy(murl, Line);
  250.                         while(*Line !='\0'){
  251.                                 if(*Line=='[' && *(Line+1)==':' && ('0'<=*(Line+2) && *(Line+2)<='9') && *(Line+3)==']'){
  252.                                         renMARK[*(Line+2)-48]=TRUE;
  253.                                         Line+=4;
  254.                                 }else{
  255.                                         Line++;
  256.                                 }
  257.                         }
  258.                         urlMARK=TRUE;
  259.                         continue;
  260.        
  261.                 }else if(
  262.                         (urlMARK)                     &&
  263.                         (Line[0]=='[' &&Line[1]==':') &&
  264.                         ('0'<=Line[2] &&Line[2]<='9') &&
  265.                         (Line[3]==']' &&Line[4]=='=')
  266.                        
  267.                 ){
  268.                         SN=Line[2]-48;
  269.                         if(!renMARK[SN]){continue;}

  270.                         strcpy(settingini[SN], Line);

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

  274.                         }else if(renMARK[SN]){

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

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

  280.                                 }else if(tmps!=NULL){               
  281.                                         if(*zp=='0'){
  282.                                                 while('0'<= *zp && *zp <='9'){
  283.                                                         Z[SN]++;
  284.                                                         zp++;
  285.                                                 }
  286.                                         }
  287.                                         M[SN]=atoi(snumsrc), N[SN]=atoi(tmps);
  288.                                         if(M[SN]>N[SN]){
  289.                                                 int exnum=M[SN];
  290.                                                 M[SN]=N[SN], N[SN]=exnum;
  291.                                         }
  292.                                 }
  293.                         }       
  294.                 }
  295.         }       
  296.         fclose(fp);
  297.        
  298.         //统计总循环次数
  299.         for(int i=0; i<10; i++){totalCYC *=N[i]-M[i]+1;}
  300.         return 0;
  301. }

  302. /*************下载函数*************/
  303. UINT WINAPI FastDownload(void* ptr)
  304. {
  305.         //分配URL字串
  306.         char* ptftr=(char*)calloc(16, sizeof(char));
  307.         char* aurl =(char*)calloc(SAFE_SIZE, sizeof(char));
  308.         char* dest =(char*)calloc(SAFE_SIZE, sizeof(char));
  309.         char* durl =(char*)calloc(SAFE_SIZE, sizeof(char));
  310.         char* titl =(char*)calloc(SAFE_SIZE, sizeof(char));
  311.         durl[0]='.', durl[1]='\\';

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

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

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

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

  325.         //定义URL指针
  326.         char *purl=NULL, *surl=NULL, *pdit=NULL;
  327.        
  328.         //启动十层循环
  329.         for(i[0]=snum; i[0]<=lnum; i[0]++)
  330.         for(i[1]=M[1]; i[1]<=N[1]; i[1]++)
  331.         for(i[2]=M[2]; i[2]<=N[2]; i[2]++)
  332.         for(i[3]=M[3]; i[3]<=N[3]; i[3]++)
  333.         for(i[4]=M[4]; i[4]<=N[4]; i[4]++)
  334.         for(i[5]=M[5]; i[5]<=N[5]; i[5]++)
  335.         for(i[6]=M[6]; i[6]<=N[6]; i[6]++)
  336.         for(i[7]=M[7]; i[7]<=N[7]; i[7]++)
  337.         for(i[8]=M[8]; i[8]<=N[8]; i[8]++)
  338.         for(i[9]=M[9]; i[9]<=N[9]; i[9]++){

  339.                    surl=murl, purl=aurl;

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

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

  343.                                 SN=*(surl+2)-48;
  344.                                
  345.                                 if(S[SN][0] !=NULL){
  346.                                         pdit=S[SN][i[SN]];
  347.                                 }else{                       
  348.                                         if(Z[SN] >0){
  349.                                                 sprintf(ptftr, "%%0%dd", Z[SN]);
  350.                                                 sprintf(dest, ptftr, i[SN]);

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

  353.                                         }else{
  354.                                                 sprintf(dest, "%d",  i[SN]);
  355.                                         }
  356.                                         pdit=dest;
  357.                                 }
  358.                                
  359.                                 while(*pdit !='\0'){
  360.                                         *(purl++)=*(pdit++);               
  361.                                 }
  362.                                 surl+=4;
  363.                                        
  364.                         }else{
  365.                                 *(purl++)=*(surl++);
  366.                         }
  367.                 }
  368.                 //置结束符
  369.                 *purl='\0';

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

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

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

  377.                 //根据网址创建目录
  378.                 while(*turl != '\0'){
  379.                         switch(*turl)
  380.                         {
  381.                         case '/':
  382.                                 *sp='\0';
  383.                                 if(_access(durl, FILE_EXIST) != 0){
  384.                                         _mkdir(durl);
  385.                                 }
  386.                                 *sp='\\';
  387.                                 break;
  388.                                
  389.                         case ':':
  390.                         case '*':
  391.                         case '?':
  392.                         case '"':
  393.                         case '>':
  394.                         case '<':
  395.                         case '|':
  396.                                 *sp='@';
  397.                                 break;
  398.                                
  399.                         default:
  400.                                 *sp=*turl;
  401.                                 break;
  402.                         }               
  403.                         //指针移位
  404.                         sp++, turl++;
  405.                 }
  406.                 //置结束符
  407.                 *sp='\0';

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

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

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

  422.                 //下载状态更新
  423.                 preMARK=nowMARK;
  424.         }

  425.         //释放数组内存
  426.         free(aurl);
  427.         free(durl);
  428.         free(dest);
  429.         free(titl);
  430.         free(ptftr);
  431.        
  432.         //线程结束
  433.         nowsThread--;
  434.         if(*outlog != 0){
  435.                 //fprintf(logfp, "\nThe %dth thread end!\n\n", nThreadID+1);
  436.         }
  437.         return (UINT)0;
  438. }

  439. /*************MAIN函数*************/
  440. int main(int argc, char** argv)
  441. {
  442.         int threadNUMS=100;
  443.         char K, *outLOG=NULL;
  444.         while((K=GetOpt(argc,argv,"hi:n:p:l:"))!=-1)
  445.         {
  446.                 switch(K)
  447.                 {
  448.                 case 'h':
  449.                 case 'H':
  450.                         fprintf(stdout, HELP_INFORMATION);
  451.                         exit(0);

  452.                 case 'i':
  453.                 case 'I':
  454.                         if(OPTARG !=NULL){
  455.                                 strcpy(inifile, OPTARG);
  456.                         }
  457.                         break;

  458.                 case 'l':
  459.                 case 'L':
  460.                         if(OPTARG !=NULL){
  461.                                 strcpy(outlog, OPTARG);
  462.                         }
  463.                         break;

  464.                 case 'n':
  465.                 case 'N':
  466.                         if(OPTARG !=NULL){
  467.                                 int exnum=atoi(OPTARG);
  468.                                 threadNUMS=(0<exnum && exnum<SAFE_SIZE*4)?exnum:SAFE_SIZE*4;
  469.                         }
  470.                         break;

  471.                 case 'r':
  472.                 case 'R':
  473.                         if(OPTARG !=NULL){
  474.                                 strcpy(mpath, OPTARG);
  475.                         }
  476.                         break;

  477.                 default:
  478.                         fprintf(stdout, "Unknown switch '%c'\n", K);
  479.                         exit(1);
  480.                 }
  481.         }

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

  491.         if(argc==1){
  492.                 //无参数则退出
  493.                 fprintf(stdout, HELP_INFORMATION);
  494.                 exit(0);
  495.         }

  496.         //判断根目录是否存在
  497.         if(_access(mpath, FILE_EXIST)!=0){
  498.                 _mkdir(mpath);
  499.         }
  500.         if(_access(mpath, FILE_EXIST)==0){
  501.                 //切换至下载目录
  502.                 _chdir(mpath);
  503.         }else{
  504.                 //无法创建根目录则退出
  505.                 fprintf(stdout, "Can not creat the root folder\n");
  506.                 exit(1);       
  507.         }

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

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

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

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

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

  528.         //创建时间结构体
  529.         time_t startTIME, endTIME;
  530.         struct tm* timeinfo;
  531.         time(&startTIME);
  532.         timeinfo=localtime(&startTIME);

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

  536.         //是否开启日志输出
  537.         if(*outlog != 0){
  538.                 logfp=fopen(outlog, "w");
  539.                 if(logfp == NULL){
  540.                         fprintf(stdout, "Open log failed\n");
  541.                         exit(1);
  542.                 }else{
  543.                         fprintf(logfp,
  544.                                 "================================================================\n"
  545.                                 "The purl log file, Time: %s"
  546.                                 "================================================================\n\n"
  547.                                 ,asctime(timeinfo)
  548.                         );
  549.                         fprintf(logfp, "[Threads num]\n%d\n\n", rThreadRange);
  550.                         fprintf(logfp, "[Root path]\n%s\n\n", mpath);
  551.                         fprintf(logfp, "[The URL regular]\n%s\n\n", murl);
  552.                         fprintf(logfp, "[Setting ini]\n");
  553.                         for(int i=0; i<=9; i++){
  554.                                 if(settingini[i][0]!=0){
  555.                                         fprintf(logfp, "%s\n", settingini[i]);
  556.                                 }
  557.                         }
  558.                         fprintf(logfp, "\n[Start the download time]\n%s\n", asctime(timeinfo));
  559.                         fprintf(logfp, "[Successfully downloaded URL]\n");
  560.                 }
  561.         }
  562.         //隐藏光标
  563.         DispyCursor((DWORD)25, FALSE);
  564.         //显示目标网站IP
  565.         DownloadURLtoIP(handle_out, murl);

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

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

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

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

  578.                  if(phaThread[i]==0){
  579.                             nErr=GetLastError();
  580.                             if(nErr==0x08){
  581.                                         printf("\nOpen thread failed, lack of storage space!\n");
  582.                         }else{
  583.                                 printf("\nOpen thread failed, error number%d\n", nErr);
  584.                         }
  585.                         break;
  586.                 }
  587.                 WaitForSingleObject(ghDataEvent, INFINITE);
  588.         }

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

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

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

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

  596.         //绘制进度条
  597.         int spi=0;
  598.        
  599.         do{
  600.                 //进度百分数
  601.                 int i=(totalCYC==0)?100:(prointThread*100/totalCYC), j=i/2;
  602.                 if(spi==j){
  603.                         //缓解CPU占用
  604.                         Sleep(30);
  605.                         continue;
  606.                 }

  607.                 //显示递增进度
  608.                 while(spi<j){
  609.                         fputc('=', stdout);
  610.                         spi++;
  611.                 }

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

  614.                 //线程退出器
  615.                 if(prointThread==totalCYC){
  616.                         break;
  617.                 }

  618.         }while(nowsThread);

  619.         //补全百分百进度
  620.         if(prointThread==totalCYC){
  621.                 while(spi<50){
  622.                         fputc('=', stdout);
  623.                         spi++;
  624.                 }
  625.                 fprintf(stdout, "100%%");
  626.         }
  627.         fprintf(stdout, "\n");

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

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

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

  637.         //关闭日志读写
  638.         if(*outlog != 0){
  639.                 fprintf(logfp, "\n[End the download time]\n%s\n", asctime(timeinfo));
  640.                 fprintf(logfp, "[Download time-spending]\n%g seconds\n\n", difftime(endTIME, startTIME));
  641.                 fprintf(logfp, "[Percent of completion]\n%d%%\n\n", (prointThread==totalCYC)?100:spi*2);
  642.                 fprintf(logfp, "[Successfully downloaded files]\n%d", trueDownload);
  643.                 fclose(logfp);
  644.         }
  645.         return 0;
  646. }
复制代码

评分

参与人数 2技术 +2 收起 理由
freesoft00 + 1 +1
老刘1号 + 1 666

查看全部评分

发表于 2017-8-26 01:13:46 | 显示全部楼层
是我用错了吗?怎么不行。

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中,也不行。弹出错误。
 楼主| 发表于 2017-8-26 08:26:01 | 显示全部楼层
本帖最后由 happy886rr 于 2017-8-26 09:07 编辑

回复 2# freesoft00
代码已经修复,这是多线程批量下载器,只支持批量地址下载,比如www.a01.com, www.a02.com, www.a03.com就是批量的网址,而不是说单一下载某个文件。
单独下载某个文件请使用pget。
purl的目的是针对有规律的数字递增网址,批量多线程下载,而且必须是几千、几万的批量网址才可以成功下载。线程过少的话,主程序很快就跑完了,子线程也就结束了。我把下载量调到5000,你的文件都成功下载了[:0]=0-5000
purl是针对繁重的批量下载任务定制的,个别几个小文件的下载多线程会得不偿失,小文件请使用pget。
发表于 2017-8-26 11:46:23 | 显示全部楼层
回复 3# happy886rr


    哦,知道了。用途不一样呀。
发表于 2017-9-14 14:39:01 | 显示全部楼层
支持  ssh 链接的 sftp  下载吗?
发表于 2017-10-10 00:37:58 | 显示全部楼层
请教下要怎么编译?
gcc和vs均未通过
发表于 2017-10-10 09:49:20 | 显示全部楼层
本帖最后由 523066680 于 2017-10-10 10:02 编辑

回复 6# CrLf


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

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

  2. // #pragma comment(lib, "ws2_32.lib")
  3. // #pragma comment (lib,"urlmon.lib")
复制代码
gcc purl.c -lws2_32 -lurlmon
 楼主| 发表于 2017-10-10 13:39:14 | 显示全部楼层
本帖最后由 happy886rr 于 2017-10-10 14:10 编辑

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

评分

参与人数 1技术 +1 收起 理由
CrLf + 1 666

查看全部评分

发表于 2019-6-28 13:11:34 | 显示全部楼层
回复 8# happy886rr

手机版本的编译器在哪里?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 23:22 , Processed in 0.024810 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表