- 浏览: 35295 次
- 性别:
- 来自: 北京
最新评论
-
firefox_hit:
您好,请问在哪里可以下载到此WebSpider的源码呢?我想学 ...
开放源码的网络蜘蛛 -
dying:
谢谢分享,不过写代码没注释的习惯真差
C语言写的多线程下载器 -
zkf53064:
...
C语言写的多线程下载器 -
iranger:
在load中使用LockMode.write是肯定不对的,AP ...
LockMode.UPGRADE 引发的对于Hibernate事务的思考 -
pn2008:
学习。。。。
LockMode.UPGRADE 引发的对于Hibernate事务的思考
1.软件介绍
qdown是一款开源的HTTP多线程下载软件。
特点:多线程,支持服务器重定向,支持断点续传。
平台:Solaris/FreeBSD/Windows(CygWin)
作者:小孙
2.如何使用
usage: qdown URL [thread_amount] [save as]
example: qdown http://www.baidu.com/img/logo.gif 5 /home/sunjoy/log.gif
3.如何编译
On Solaris: cc -lsocket -lnsl qdown.c
On FreeBSD: gcc -pthread qdown.c
或者用sunstudio打开工程文件编译
4.基本原理
4.1 多线程原理
HTTP协议规定在请求报头中加入Range: bytes=%d-%d (%d代表整数)来下载指定范围的块儿,
因此根据文件的总大小,qdown开启多个线程分别下载各个部分,最终完成下载整个文件。
4.2 服务器重定向
很多情况下,当客户端发起GET请求后,服务器可能通过Location: xxxxx来告诉客户端重定向
到新的URL,当qdown遇到这种情况时会去下载新的URL指定的文件。qdown最多允许5次重定向。
4.3 断点续传
由于程序被中断或者网络故障等原因可能导致一个文件没有下载完全。qdown在下载过程中会
维护一个.cfg文件来记录个线程的下载情况,当重新下载时,qdown会根据.cfg文件的记录从
上次断掉的地方开始下载。
5.改进方向
预计在下一版本中加入对FTP URL的支持
qdown是一款开源的HTTP多线程下载软件。
特点:多线程,支持服务器重定向,支持断点续传。
平台:Solaris/FreeBSD/Windows(CygWin)
作者:小孙
2.如何使用
usage: qdown URL [thread_amount] [save as]
example: qdown http://www.baidu.com/img/logo.gif 5 /home/sunjoy/log.gif
3.如何编译
On Solaris: cc -lsocket -lnsl qdown.c
On FreeBSD: gcc -pthread qdown.c
或者用sunstudio打开工程文件编译
4.基本原理
4.1 多线程原理
HTTP协议规定在请求报头中加入Range: bytes=%d-%d (%d代表整数)来下载指定范围的块儿,
因此根据文件的总大小,qdown开启多个线程分别下载各个部分,最终完成下载整个文件。
4.2 服务器重定向
很多情况下,当客户端发起GET请求后,服务器可能通过Location: xxxxx来告诉客户端重定向
到新的URL,当qdown遇到这种情况时会去下载新的URL指定的文件。qdown最多允许5次重定向。
4.3 断点续传
由于程序被中断或者网络故障等原因可能导致一个文件没有下载完全。qdown在下载过程中会
维护一个.cfg文件来记录个线程的下载情况,当重新下载时,qdown会根据.cfg文件的记录从
上次断掉的地方开始下载。
5.改进方向
预计在下一版本中加入对FTP URL的支持
/** ** description:qdown is a multithread downloader ** author:Sunjoy ** email:fxsjy @@@ yahoo.com.cn ** from:ICT.CAS. ** date:2007-9-10 ** */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <pthread.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define MAX_THREAD 100 typedef struct URLInfo { char schema[8]; char host[256]; char host_name[256]; unsigned int port; char file[256]; }URLInfo; typedef struct Connection { int sock; URLInfo url_info; int avaliable; }Connection; typedef struct Resource { char file_url[256]; int file_size; char file_name[256]; }Resource; typedef struct ThreadArg { Resource* res; int start_pos; int limit; int no; }ThreadArg; typedef struct BreakPoint { int downloaded; int thread_amount; int tasks[MAX_THREAD][2]; }BreakPoint; pthread_mutex_t g_mut; int g_total=0; int g_downloaded=0; BreakPoint g_breakpoint; URLInfo parse_url(const char *url); Connection open_url(const char * url); Resource get_resource(const char *url); void join_url(const char* old_url,const char* redirect,char * new_url); void download(const char* url,int thread_amount,const char* file_name); void* download_part(void* args); void* monitor(void *args); void store_breakpoint(char * cfgName); void store_breakpoint(char * cfgName) { int z; FILE* f; f=fopen(cfgName,"w"); fprintf(f,"%d\n",g_breakpoint.downloaded); fprintf(f,"%d\n",g_breakpoint.thread_amount); for(z=0;z<g_breakpoint.thread_amount;z++){ fprintf(f,"%d-%d\n",g_breakpoint.tasks[z][0],g_breakpoint.tasks[z][1]); } fclose(f); } void join_url(const char* old_url,const char* redirect,char * new_url) { char stack1[256][256]={0},stack2[256][256]={0}; int i=0,j=0,p1=0,p2=0; char seg[256]={0}; URLInfo temp_urlinfo; memset(new_url,0,sizeof(new_url)); if(strstr(redirect,"://")!=NULL){ strcpy(new_url,redirect); } else{ while(1){ while(redirect[i]!='/' && redirect[i]!=0){ seg[j++]=redirect[i++]; } strcpy(stack1[p1++],seg); memset(seg,0,sizeof(seg)); j=0; if(redirect[i]==0) break; i++; } for(i=0;i<p1;i++){ if(!strcmp(stack1[i],"..") && p2>-1) p2--; else if(strcmp(stack1[i],".")){ strcpy(stack2[p2++],stack1[i]); } } //printf("##%s\n",stack2[0]); if(!strcmp(stack2[0],"")){ temp_urlinfo=parse_url(old_url); sprintf(new_url,"%s://%s:%d/",temp_urlinfo.schema,temp_urlinfo.host,temp_urlinfo.port); } else{ i=strlen(old_url)-1; while(old_url[i]!='/') i--; //printf("##%c\n",old_url[i]); strncpy(new_url,old_url,i+1); new_url[i+1]=0; } //printf("##%s\n",new_url); for(j=0;j<p2-1;j++){ strcat(new_url,stack2[j]); strcat(new_url,"/"); } strcat(new_url,stack2[p2-1]); } } URLInfo parse_url(const char* url){ int i=0,j=0; char schema[8]={0}; char host[256]={0}; char port[8]={0}; char file[256]={0}; char IP[32]={0}; URLInfo url_info; struct hostent* hptr; while(url[i]!=':'){ schema[j++]=url[i++]; } for(i+=3,j=0;url[i]!=':' && url[i]!='/' && url[i]!=0;){ host[j++]=url[i++]; } if(url[i]==':'){ for(i+=1,j=0;url[i]!='/';){ port[j++]=url[i++]; } sscanf(port,"%d",&url_info.port); } else{ url_info.port=80; } if(url[i]!=0){ for(j=0;url[i]!=0;){ file[j++]=url[i++]; } } else{ file[0]='/'; } strcpy(url_info.schema,schema); strcpy(url_info.file,file); strcpy(url_info.host_name,host); hptr=gethostbyname(host); if(hptr!=NULL){ strcpy(url_info.host, inet_ntop(hptr->h_addrtype,*(hptr->h_addr_list),IP,sizeof(IP)) ); } //printf("%s\n",url_info.host); return url_info; } Connection open_url(const char* url){ Connection conn; struct sockaddr_in remote_addr,local_addr; conn.avaliable=0; conn.url_info=parse_url(url); local_addr.sin_family=AF_INET; local_addr.sin_addr.s_addr=htonl(INADDR_ANY); local_addr.sin_port=htons(0); remote_addr.sin_family=AF_INET; remote_addr.sin_addr.s_addr=inet_addr(conn.url_info.host); remote_addr.sin_port=htons(conn.url_info.port); conn.sock=socket(AF_INET,SOCK_STREAM,0); if(bind(conn.sock, (struct sockaddr*)&local_addr, sizeof(local_addr))<0){ printf("bind error\n"); } if(conn.sock){ if( connect(conn.sock,(struct sockaddr*)&remote_addr,sizeof(remote_addr))!=-1 ){ conn.avaliable=1; } } return conn; } Resource get_resource(const char* url){ char pack[1024]={0}; char buf[1024]={0}; char redirect[256]={0},new_url[256]={0},old_url[256]={0}; static int redirect_count=0; char* i; char* j; char* z; Resource res; Connection conn=open_url(url); if(!conn.avaliable){ return res; } sprintf(pack,"GET %s HTTP/1.1\nHost: %s\nAccept: */*\nReferer: http://%s\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)\nPragma: no-cache\nCache-Control: no-cache\nConnection: close\n\n",conn.url_info.file,conn.url_info.host_name,conn.url_info.host_name); send(conn.sock,pack,strlen(pack),0); recv(conn.sock,buf,sizeof(buf),0); //printf("%s\n",buf); if(strstr(buf,"HTTP/1.1 404")!=NULL || strstr(buf,"HTTP/1.0 404")!=NULL){ return res; } i=(char *)strstr(buf,"Location:"); if(i!=NULL && redirect_count<5){ sscanf(i,"Location: %s",redirect); sprintf(old_url,"%s://%s:%d%s",conn.url_info.schema,conn.url_info.host_name,conn.url_info.port,conn.url_info.file); join_url(old_url,redirect,new_url); //printf("@#%s\n",new_url); redirect_count++; return get_resource(new_url); } i=(char *)strstr(buf,"Content-Length:"); if(i!=NULL){ sscanf(i,"Content-Length: %d",&res.file_size); } strcpy(res.file_url,url); //printf("#%d\n",res.file_size); for(z=(char*)url;(j=strstr(z,"/"))!=NULL;){ z=j+sizeof(char); } strcpy(res.file_name,z); close(conn.sock); return res; } void* download_part(void * args) { ThreadArg* targ=(ThreadArg*)args; Connection conn; FILE* f=NULL; char pack[1024]={0}; char buf[1024]={0}; int i=0,ct=0; char* body=NULL; //printf("%s,%d-%d\n",targ->res->file_url, targ->start_pos,targ->limit); conn=open_url(targ->res->file_url); while(!conn.avaliable){ sleep(1); conn=open_url(targ->res->file_url); } if(conn.avaliable){ f=fopen(targ->res->file_name,"rb+"); fseek(f,targ->start_pos,0); sprintf(pack,"GET %s HTTP/1.1\nHost: %s\nAccept: */*\nReferer: http://%s\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)\nRange: bytes=%d-%d\nPragma: no-cache\nCache-Control: no-cache\n\n",conn.url_info.file,conn.url_info.host_name,conn.url_info.host_name,targ->start_pos,targ->start_pos+targ->limit-1); //printf("%s",pack); begin_down: send(conn.sock,pack,strlen(pack),0); i=recv(conn.sock,buf,sizeof(buf),0); if(strstr(buf,"HTTP/1.1 206")==NULL && strstr(buf,"HTTP/1.0 206")==NULL && strstr(buf,"HTTP/1.1 200")==NULL && strstr(buf,"HTTP/1.0 200")==NULL){ sleep(2); memset(buf,0,sizeof(buf)); conn=open_url(targ->res->file_url); goto begin_down; } //printf("##%s\n",body); body=strstr(buf,"\r\n\r\n")+4; if(body!=NULL){ i=i-(body-buf); fwrite(body,sizeof(char),i,f); //printf("@@@@%x\n",buf); fflush(f); ct+=i; pthread_mutex_lock(&g_mut); g_downloaded+=i; pthread_mutex_unlock(&g_mut); while(ct< targ->limit){ i=recv(conn.sock,buf,sizeof(buf),0); if(i==0){ fclose(f); conn.avaliable=0; while(!conn.avaliable){ sleep(2); //printf("waiting...\n"); conn=open_url(targ->res->file_url); } memset(pack,0,sizeof(pack)); memset(buf,0,sizeof(buf)); sprintf(pack,"GET %s HTTP/1.1\nHost: %s\nAccept: */*\nReferer: http://%s\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)\nRange: bytes=%d-%d\nPragma: no-cache\nCache-Control: no-cache\n\n",conn.url_info.file,conn.url_info.host_name,conn.url_info.host_name,targ->start_pos+ct,targ->start_pos+targ->limit-1); f=fopen(targ->res->file_name,"rb+"); fseek(f,targ->start_pos+ct,0); goto begin_down; } fwrite(buf,sizeof(char),i,f); fflush(f); ct+=i; pthread_mutex_lock(&g_mut); g_downloaded+=i; g_breakpoint.tasks[targ->no][0]=targ->start_pos+ct; g_breakpoint.tasks[targ->no][1]=targ->limit-ct; g_breakpoint.downloaded=g_downloaded; pthread_mutex_unlock(&g_mut); } fclose(f); g_breakpoint.downloaded=g_downloaded; close(conn.sock); } } pthread_exit(NULL); } void* monitor(void* args){ float p; int i,j,z,old; FILE* f; char cfgName[256]; strcpy(cfgName,(char*)args); strcat(cfgName,".cfg"); while(1){ p=g_downloaded/(g_total+0.0); if(g_downloaded>=g_total) break; i=p*100/10; if(old!=g_downloaded){ printf("\r"); for(j=0;j<i;j++){ printf("=="); } printf("%2.0f%%",p*100); fflush(stdout); store_breakpoint(cfgName); old=g_downloaded; } } printf("\r====================100%%\n"); remove(cfgName); pthread_exit(NULL); } void download(const char* url,int thread_amount,const char* file_name) { ThreadArg targs[MAX_THREAD]; pthread_attr_t * thAttr = NULL; pthread_t tids[MAX_THREAD],monitor_id,controler_id; Resource res; int i,block_size,t_start_pos,t_limit; FILE* f; char cfgName[256]={0}; if(thread_amount>MAX_THREAD) return; res=get_resource(url); if(!strcmp(res.file_url,"")) return; if(strcmp(file_name,"")) strcpy(res.file_name,file_name); if(!strcmp(res.file_name,"")) strcpy(res.file_name,"default_down"); if(res.file_size<1000000) thread_amount=1; block_size=res.file_size/thread_amount; pthread_mutex_init(&g_mut,NULL); strcpy(cfgName,res.file_name); strcat(cfgName,".cfg"); printf("downloading %s,%d bytes... \n",res.file_name,res.file_size); if(fopen(cfgName,"r")==NULL){ new_task: f=fopen(res.file_name,"wb"); if(f==NULL){ strcpy(res.file_name,"default_down"); f=fopen(res.file_name,"wb"); } fclose(f); g_total=res.file_size; for(i=0;i<thread_amount;i++){ targs[i].res=&res; targs[i].start_pos=block_size*i; targs[i].limit=block_size; if(i==thread_amount-1) targs[i].limit+= (res.file_size%thread_amount); targs[i].no=i; g_breakpoint.tasks[i][0]=targs[i].start_pos; g_breakpoint.tasks[i][1]=block_size; pthread_create(&tids[i], thAttr, download_part, (void *)&targs[i]); } } else{ f=fopen(cfgName,"r"); if(fscanf(f,"%d",&g_downloaded)==-1) goto new_task; //printf("#%d\n",g_downloaded); g_total=res.file_size; fscanf(f,"%d",&thread_amount); for(i=0;i<thread_amount;i++){ fscanf(f,"%d-%d",&t_start_pos,&t_limit); targs[i].res=&res; targs[i].start_pos=t_start_pos; targs[i].limit=t_limit; targs[i].no=i; g_breakpoint.tasks[i][0]=targs[i].start_pos; g_breakpoint.tasks[i][1]=t_limit; pthread_create(&tids[i], thAttr, download_part, (void *)&targs[i]); } fclose(f); } pthread_create(&monitor_id,NULL,monitor,(void *)res.file_name); g_breakpoint.thread_amount=thread_amount; g_breakpoint.downloaded=g_downloaded; //printf("#%d\n",g_downloaded); /*for(i=0;i<thread_amount;i++){ pthread_join(tids[i],NULL); }*/ pthread_join(monitor_id,NULL); } int main (int ac, char * av[]) { int thread_amount=5; char file_name[256]={0}; if(ac<2){ printf("usage: qdown URL [thread_amount] [save as]\n"); printf("example: qdown http://www.baidu.com/img/logo.gif 5 /home/sunjoy/log.gif\n"); } else{ if(ac>=3) sscanf(av[2],"%d",&thread_amount); if(ac>=4){ strcpy(file_name,av[3]); } download(av[1],thread_amount,file_name); } return 0; }
相关推荐
用于微处理器、微控制器和 DSP 的紧凑、可靠、高性能和线程安全的嵌入式文件系统。可选的日志组件提供故障安全操作,同时保持 FAT 兼容性。 µC/OS 是最初由 Micriµm 开发的全功能嵌入式操作系统。除了两个非常...
与进程不同,Bento-boxes 不需要多线程或虚拟内存。与文件和管道不同,盒子使用类型丰富的盒子间通信 (IBC) 机制进行通信,这些机制的行为类似于熟悉的 C 函数,但有一些限制。 便当盒由两件事来描述: 一组内存...
特征: 抢占式或协作式调度(取决于您的配置) 对于电池供电的应用程序可以无滴答声 二进制和计数信号量 具有优先级上限或优先级继承的互斥锁 线程安全通信的队列 ...更多详情、使用方法,请下载后阅读README.md文件
VS_2008_速成版_下载和安装.mp4 大家可以学的C语言 ABG2C_Cpp_更强大的C.mp4 ABG2C_for_循环.mp4 ABG2C_两个预处理器指令.mp4 ABG2C_从何处入手.mp4 ABG2C_关系运算符.mp4 ABG2C_初识C语言.mp4 ABG2C_...
入门 最快的入门方法是使用以下电路板支持包之一: 核144 STM32H735G-DK 上述项目提供了快速轻松地克隆和构建所需代码的说明。 关于 Stratify OS 是专为 ARM Cortex...更多详情、使用方法,请下载后阅读README.md文件
提供了x86、x64dll、qt示例、C#封装对象代码及示例项目,不包含播放器c语言源码,请根据需要下载。版本v1.3.15。原文链接:https://blog.csdn.net/u013113678/article/details/124759757。 * 更新日志 * v1.3:支持...
根据不同的webserver,也就是应用程序服务器,在处理应用请求的时候,有些是用多线程而非多进程的方式,那么由于线程会牵扯到共享寄存器和内存方面的,所以很容易出错(考虑c语言指针的情况),那么系统就需要时间和...
使用GeoGeo的线程函数,你可以只写一个关键字thread就开辟一个新线程;使用进程函数,只写一个process关键字就可以将GeoGeo程序部署到网络上进行多机并行计算;你还可以开辟仅受磁盘空间大小限制的大数据集数组;...
多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户空间(User-Space) 实现所有这些任务,所以没有这些问题。此模型的...
FFTW2.1.5 支持共享存储多线程并行和分布式存储 MPI 并行。FFTW 的运算性能远远领先于目前已有的其它 FFT 软件。 FFTW 为任意大小的模式生成一个计划(plan),通过对该计划施行各种运算完成各种模式的转换;内部...
多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户空间(User-Space) 实现所有这些任务,所以没有这些问题。此模型的...
30_多线程下载原理.avi 所在项目:net 31_多线程断点下载器.avi 所在项目:MulThreadDownloader 32_文件断点上传器.avi 所在项目:videoUpload & javaSE应用:socket 33_为应用添加多个Activity与参数传递.avi 所在...
30_多线程下载原理.avi 所在项目:net 31_多线程断点下载器.avi 所在项目:MulThreadDownloader 32_文件断点上传器.avi 所在项目:videoUpload & javaSE应用:socket 33_为应用添加多个Activity与参数传递.avi 所在...
第9章 多线程编程 9.1 Linux下线程概述 9.2 Linux线程实现 9.3 实验内容——“生产者消费者”实验 本章小结 思考与练习 第10章 嵌入式Linux网络编程 10.1 TCP/IP协议概述 10.2...
节点ffi-napiN-API的Node.js外部功能接口 node-ffi-napi是一个Node.js插件,用于使用纯... 但是,在垃圾回收和多线程执行的上下文中,API没有非常明确定义的属性。 如果可能,建议避免使用此库的任何多线程用法。
第9章 多线程编程 279 9.1 Linux下线程概述 279 9.1.1 线程概述 279 9.1.2 线程分类 280 9.1.3 Linux线程技术的发展 280 9.2 Linux线程实现 281 9.2.1 线程基本操作 281 9.2.2 线程访问控制 ...
第9章 多线程编程 9.1 Linux线程概述 9.1.1 线程概述 9.1.2 线程机制的分类和特性 9.2 Linux线程编程 9.2.1 线程基本编程 9.2.2 线程之间的同步与互斥 9.2.3 线程属性 9.3 实验内容——“生产者消费者”实验 9.4 本...