//代码类似https多线程下载,整体实现逻辑类似,区别比较大的是curl_opt的相关参数设置不一样
#include <iostream> #include <fstream> #include <curl/curl.h> #include <pthread.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> using namespace std; #define THREADS_NUMS (10) class FileInfo { public: void * pFile; size_t offset; size_t endpos; char * pUrl; pthread_t tid; size_t used; FILE * file; size_t totalLen; }; FileInfo cFiles[THREADS_NUMS+1]; char buffer[64]={0}; long dwLen=0; //处理下载进度 int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow){ if (dltotal != 0) { //printf("%lf / %lf (%lf %%)\n", dlnow, dltotal, dlnow*100.0 / dltotal); long totalUsedLen=0; //long totalLen=0; for(int i=0;i<THREADS_NUMS+1;i++) { totalUsedLen+=cFiles[i].used; totalUsedLen+=cFiles[i].totalLen; } printf("%ld / %ld (%ld %%)\n",totalUsedLen,dwLen,totalUsedLen*100/dwLen); } return 0; } //获取ftp需要下载文件的大小 static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata) { /* received header is nitems * size long in 'buffer' NOT ZERO TERMINATED */ /* 'userdata' is set with CURLOPT_HEADERDATA */ long duLen=0; if(sscanf(buffer,"Content-Length: %ld\n",&duLen)) { *(long *)userdata=duLen; } return nitems*size; } //获取ftp需要下载文件的大小 double getFileLength(char * pUrl,char * usr,char * pwd) { CURL * pCurl=curl_easy_init(); if(NULL==pCurl) { cout<<"curl_easy_init error!"<<endl; return false; } snprintf(buffer,64,"%s:%s",usr,pwd); curl_easy_setopt(pCurl,CURLOPT_URL,pUrl); curl_easy_setopt(pCurl,CURLOPT_HEADER ,1); curl_easy_setopt(pCurl,CURLOPT_NOBODY ,1); curl_easy_setopt(pCurl,CURLOPT_USERPWD,buffer); curl_easy_setopt(pCurl, CURLOPT_HEADERFUNCTION, header_callback);//设置头文件处理函数(获取ftp需要下载的文件大小) curl_easy_setopt(pCurl, CURLOPT_HEADERDATA, &dwLen); CURLcode tRet=curl_easy_perform(pCurl); if(0!=tRet) { cout<<"curl_easy_perform error"<<endl; return false; } curl_easy_cleanup(pCurl); return dwLen; } //各线程分别写自己对应的位置 size_t writeFile(void *pData, size_t dwSize, size_t dwMemb, void * pFile) { FileInfo * pFileInfo=(FileInfo *)pFile; cout<<"id: "<<pFileInfo->tid<<" offset: "<<pFileInfo->offset<<endl; cout<<"dwSize*dwMemb: "<<dwSize*dwMemb<<endl; memcpy((char *)pFileInfo->pFile+pFileInfo->offset,(char *)pData,dwSize*dwMemb); pFileInfo->offset+=dwSize*dwMemb; pFileInfo->used+=dwSize*dwMemb; return dwSize*dwMemb; } void * works(void * arg) { FileInfo * pFile=(FileInfo *)arg; CURL * pCurl=curl_easy_init(); if(NULL==pCurl) { cout<<"curl_easy_init error!"<<endl; return NULL; } if(pFile->file) { cout<<"hello"<<endl; fscanf(pFile->file,"%ld-%ld-%ld",&pFile->offset,&pFile->endpos,&pFile->totalLen); } else { cout<<"downFile open failed"<<endl; } if(pFile->offset>=pFile->endpos-1) { cout<<pFile->tid<<" already downed: "<<pFile->offset<<"--"<<pFile->endpos<<endl; return NULL; } char range[64]={0}; snprintf(range,64,"%ld-%ld",pFile->offset,pFile->endpos); curl_easy_setopt(pCurl,CURLOPT_URL,"ftp://127.0.0.1/boost.rar");//需要下载的ftp文件链接 curl_easy_setopt(pCurl,CURLOPT_USERPWD,buffer); curl_easy_setopt(pCurl,CURLOPT_WRITEDATA,pFile->file); //CURLOPT_WRITEFUNCTION curl_easy_setopt(pCurl,CURLOPT_WRITEFUNCTION,writeFile);//写文件函数 curl_easy_setopt(pCurl,CURLOPT_WRITEDATA ,pFile); curl_easy_setopt(pCurl,CURLOPT_RANGE ,range); curl_easy_setopt(pCurl,CURLOPT_NOPROGRESS ,0L); curl_easy_setopt(pCurl,CURLOPT_PROGRESSFUNCTION,progress_callback);//下载进度显示函数 CURLcode tRet=curl_easy_perform(pCurl); if(0!=tRet) { cout<<"curl_easy_perform error"<<endl; return NULL; } curl_easy_cleanup(pCurl); } void downFtpFile(char * usr,char * pwd) { long lLen=(long)getFileLength("ftp://127.0.0.1/boost.rar",usr,pwd); cout<<lLen<<endl; int fd=open("ftpdown.txt",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR); if(fd==-1) { cout<<"open failed"<<endl; return; } if(lseek(fd,dwLen,SEEK_SET)==-1) { cout<<"lseek failed"<<endl; close(fd); return; } if(write(fd,"",1)!=1) { cout<<"write failed"<<endl; close(fd); return; } //内存映射本地的文件(放置ftp服务器上需要下载的文件) char * filePos=(char *)mmap(NULL,dwLen,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(filePos==MAP_FAILED) { close(fd); cout<<"mmap failed: "<<errno<<endl; return; } int slice=dwLen/THREADS_NUMS; FILE * file=fopen("downTemp.txt","w+"); //FILE * file=NULL; //创建THREADS_NUMS个线程,同时设置各线程在文件中的下载位置 for(int i=0;i<THREADS_NUMS+1;i++) { cFiles[i].offset=i*slice; //cFiles[i].pUrl=pUrl; cFiles[i].pFile=filePos; //cFiles[i].used=0; cFiles[i].file=file; if(i==THREADS_NUMS) { cFiles[i].endpos=dwLen-1; cFiles[i].totalLen=cFiles[i].endpos-cFiles[i].offset+1; } else { cFiles[i].endpos=(i+1)*slice-1; cFiles[i].totalLen=slice; } pthread_create(&cFiles[i].tid,NULL,works,&cFiles[i]); usleep(1); } for(int i=0;i<THREADS_NUMS+1;i++) { cout<<"tid: "<<cFiles[i].tid<<" finished"<<endl; pthread_join(cFiles[i].tid,NULL); } cout<<"00000"<<endl; fclose(file); cout<<"11111"<<endl; munmap(filePos,dwLen); cout<<"22222"<<endl; } void sighandler_func(int arg) { cout<<"arg: "<<arg<<endl; int fd=open("downTemp.txt",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR); for(int i=0;i<THREADS_NUMS+1;i++) { cFiles[i].totalLen=cFiles[i].used; //cout<<"used: "<<cFiles[i].used<<"/"<<cFiles[i].totalLen<<endl; char buffer[64]={0}; snprintf(buffer,64,"%ld-%ld-%ld\n",cFiles[i].offset,cFiles[i].endpos,cFiles[i].totalLen); write(fd,buffer,strlen(buffer)); } close(fd); exit(-1); } int main(int argc,char * * argv) { if(SIG_ERR==signal(SIGINT,sighandler_func)) { cout<<"signal error"<<endl; return 0; } downFtpFile(argv[1],argv[2]); cout<<"end"<<endl; return 0; }
玄机博客
© 版权声明
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
THE END
暂无评论内容