有许多网络文件下载工具可以在Windows平台下很好地工作,如NetAnts、“网际快车”、TelePro等,还有像WebZip那样功能强大的离线浏览器。这些工具使我们可以在Windows环境下很轻松地下载网站上的文件、目录、网站的一部分,甚至整个网站。然而在Linux环境下,这类工具却很少。笔者通过自己的摸索,在集成开发环境KDevelop 1.2下实现了一个网站下载程序,它支持文件级的“多线程下载”和“断点续传”。下面本文分3部分介绍实现这一程序的基本技术。

基本原理

1.超级链接寻径算法

要想灵活地下载一个网站的全部或部分内容,程序就必需具备从用户指定的URL开始,沿着它所包含的超级链接遍历整个网站的能力。在这个基础上根据用户的限制,筛选出所要下载的文件。

从“图论”的角度分析,网站其实是一个由文件和超级链接组成的“连通有向图”。文件是图中的顶点,超级链接是有向边。我们需要对这个有向图进行“广度优先遍历”。为此,需要用一个队列URLQueue来存放待访问的目标。初始情况下,队列中只含有用户指定的那个URL。程序从队头取得下载目标的URL,如果它符合用户的限制,就下载它指向的文件。分析此文件,找出其中包括的超级链接,生成新的下载目标的URL,然后将它们插入到队列尾部。重复以上过程,直到队列中没有符合用户限制的URL为止。

由于网站是一个“连通有向图”,所以沿着超级链接,很可能回到已经访问过的文件。为了避免程序出现死循环,要登记已经访问过的目标。在分析下载文件的超级链接时,我们要将生成的新目标的URL与已经访问过的进行比较,剔除会造成重复访问的URL。为了提高查询速度,我们采用了“哈希表”来存放从队头取出的URL。“哈希函数”可以采用将URL中的字符作为整型值相加,然后模一个质数的简单方法来实现。在本文介绍的程序中使用了质数103。

2.多线程下载和断点续传

多线程下载和断点续传使用了同一个技术。HTTP协议允许客户端在向服务器端发送下载一个文件的GET请求时,使用“Range: bytes=a1-a2"选项,要求服务器只传送指定文件中从第a1个字节到a2个字节之间的部分内容。因此下载一个文件时,可以将其分成若干段,然后启动多个线程,同时与服务器建立链接,分别传送一个文件的多个部分。最后在本地将其拼接成一个完整的文件。由于从网上下载文件时,瓶颈是在服务器端和网络传输过程中,所以采用多线程同时下载将大大提高下载速度。

当文件传输因出现问题而中断时,程序可以将各个线程当前下载的进度和已经下载的内容当做“断点信息”保存到文件中。用户下一次下载同一目标时,程序可以根据文件中保留的断点信息下载上次未完成的部分,然后将整个文件拼接起来,完成下载工作。这种技术对于在经常“掉线”的情况下下载大文件非常有利。因此,在当前流行的下载软件中都采用了此项技术。

Linux如何启动线程

1.定义一个以void *为参数、返回void *的函数。例如,为了启动下载线程,需要定义如下函数:

void * start(void * arg)

{

((CWebCopy *) arg)->DownLoad();

return arg;

}

2.在需要启动线程时,只要三条语句。例如,启动下载线程的代码如下:

#include

pthread_t tid;

pthread_create(&tid,NULL,start,arg);

部分程序的实现

以下是下载线程中三个关键性函数的算法描述(假定这三个函数都被封装在CwebCopy类中)。

int CWebCopy::DownLoad(char * host,char *path,int a1,int a2,BYTE * buf)

{

//本函数从host所指定的HTTP服务器上下载路径为path的文件中从第a1字节到第a2字节的内容,与host所指定的主机的80端口(HTTP端口)建立流式链接,共尝试5次

bool connected = false;

int sock; //用于存放套接字描述符

for(i = 0; i 

if((sock = Connect(host,80)) 

sleep(1);

else{

connected = true;

break;

}

}

if(connected){

//向指定的HTTP服务器发送GET请求,下载当前指定路径下的文件的一部分

Send(sock,“GET path%cHost: %s%cRange: bytes=%d-%d%c”,path,10,host,10,a1,a2,10);

int inflen,index = 0;

while(1){

struct timeval tv;

tv.tv_sec = 1;

tv.tv_usec = 0;

//检查套接字是否接收到了数据,尝试20次,每次间隔1秒

int readen;

readen =ReadEn(sock,tv,20);

//如果套接字中20秒内仍然没有数据,则认为超时

if(readen 

//接收数据,并存放在信息缓冲区中

inflen=read(sock,(buf+index),a2-a1); // 如果此文件所需部分已经下载结束

if(inflen <= 0) break;

}

return 0;

}

else return -1;

}

int CWebCopy ::Send(int sock,char *fmt,...)

{

//本函数将指定的字符串发送到sock所指向的远程HTTP服务器

char BUF[1024];

va_list argptr;

//处理可变个数参数

va_start(argptr,fmt);

//将参数整理成字符串后放入BUF中

vsprintf(BUF,fmt,argptr);

va_end(argptr);

//将BUF中的字符串发送到sock所指向的远程服务器

return send(sock ,BUF,strlen(BUF),0);

}

int CWebCopy ::ReadEn(int sock,struct timeval tv,int tryloop)

{

//利用select函数检验套接字sock,如果套接字接收到数据则返回“读使能”,如果出现“内部中断”以外的错误,则返回 “读禁止”

fd_set rfdset;

FD_ZERO(&rfdset);

FD_SET(sock,&rfdset);

int readen = 0;

for(int i = 0; i 

readen = select(m_sock+1,&rfdset,NULL,NULL,&tv);

if(readen>0||(readen

break;

sleep(1);

}

return readen;

}

分享到:

来源:互联网

版权声明:本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

嵌入式linux如何下载程序,Linux平台的下载程序-嵌入式系统-与非网相关推荐

  1. 嵌入式linux在windows,在Windows下启动Linux-嵌入式系统-与非网

    在Windows me下: 首先: 启动Windows me,假定光驱为g:,Linux安装在/dev/hda3,将Linux安装光盘放入光驱,在窗口DOS提示符下运行以下几条命令(注意内核文件vml ...

  2. 监护仪系统都是Linux吗,基于Linux和MiniGUI的心电监护仪设计-嵌入式系统-与非网...

    0 引言 随着人们生活节奏加快,人口逐渐老龄化,心脏疾病成为危害人类健康和生命的主要疾病之一.心电监护系统为心脏病人诊断和治疗提供了一个有效的手段,对心脏疾病的防治和诊断具有重大的意义,本介绍一种基于 ...

  3. 嵌入式linux开发环境 cpu,嵌入式Linux开发环境的搭建之:U-Boot移植-嵌入式系统-与非网...

    5.2  U-Boot移植 5.2.1  Bootloader介绍 1.概念 简单地说,Bootloader就是在操作系统内核运行之前运行的一段程序,它类似于PC机中的BIOS程序.通过这段程序,可以 ...

  4. 微信小程序 第三方平台授权小程序业务

    image 第一步:申请微信开放平台帐号并创建第三方平台 image.png image.png image.png image.png 第二步:公众号/小程序授权给第三方平台 <?php// ...

  5. 嵌入式linux编码器,基于嵌入式平台的视频编码器的实现-嵌入式系统-与非网

    引言 H.264是由ISO(国际标准化组织)/IEC(国际电工协会)和ITU(国际电信标准化部门)合作制定的新一代视频编码标准,目前正处于应用开发阶段.与以往的视频编码标准相比,h.264具有更高的压 ...

  6. linux串口驱动及应用程序,基于华邦W90P710处理器的Linux内核应用及串口驱动的实现-嵌入式系统-与非网...

    嵌入式Linux是一种很受欢迎的操作系统,具有开放源码.不存在黑箱技术.内核小.功能强大.运行稳定.效率高.易于定制裁减等特点[1],广泛应用于工控产品.很多工控产品需要和外部设备进行信息交换,而串口 ...

  7. linux嵌入式开发arm7,基于ARM7系列芯片嵌入式平台上实现的设计方案-嵌入式系统-与非网...

    本文介绍的方法是在用ARM7系列芯片S3C4510B和μClinux构建的嵌入式平台上实现的.在嵌入式系统设计过程中,系统的掉电保护越来越受到重视整个掉电保护实现的基本思路是:产生掉电信号,捕捉掉电信 ...

  8. freertos与linux区别,μClinux、μC/OS-II、eCos、FreeRTOS和djyos操作系统的特点及不足-嵌入式系统-与非网...

    基于 STM 平台且满足实时控制要求操作系统,有以下 5 种可供移植选择.分别为μClinux.μC/OS-II.eCos.FreeRTOS 和都江堰操作系统(djyos). 下面分别介绍这五种嵌入式 ...

  9. linux基金会认证考试,Linux基金会宣布新的Linux认证计划-嵌入式系统-与非网

    新计划推出首个全虚拟化.注重实际表现.不限发行版的认证考试,将有助扩大全球Linux专业人才库 Marketwired 2014年8月20日美国伊利诺伊州芝加哥消息--LINUXCON+CLOUDOP ...

最新文章

  1. 从零开始用 Flask 搭建一个网站(二)
  2. ROS发行版列表完整版
  3. sublime使用总结
  4. linux 生成字母序列,讲解在Linux平台中的Bash序列表达式(Sequence Expression)
  5. Android Studio导入github项目详解
  6. 从零开始入门 K8s| 详解 Pod 及容器设计模式
  7. SPOJ - DISUBSTR Distinct Substrings(后缀数组)
  8. NuGet 无法连接到远程服务器-解决方法(转)
  9. react context_使用React Context API-入门
  10. Linux格式化sd卡博客,linux设备驱动那点事儿之SD卡驱动理论篇
  11. 多域资源整合之基础准备--DNS配置
  12. oracle数据库pfile文件,Oracle pfile/spfile参数文件详解
  13. 整理JavaScript中,数组和字符的操作方法
  14. DevExpress ActiveX
  15. java中随机数彩票练习_跪求下面的题目答案
  16. Python 代码练习
  17. python使用Tkinter库制作文件和文件夹创建功能
  18. 如何制作一个商城小程序?
  19. 异常:The JSP specification requires that an attribute name is preceded by whitespace
  20. 浏览器下载的excel文件损坏无法打开

热门文章

  1. 在Linux程序中输出函数调用栈
  2. Chromium浏览器之渲染引擎Blink
  3. zendStudio|Eclipse 相关收藏
  4. 利用PHP的Popen实现RRDTOOL作图的动态输出
  5. oracle ogg00423,ogg实现Oracle到SQL Server 2005的同步
  6. JSP页面图片路径为中文时乱码解决办法
  7. css3 box-sizing属性
  8. Microsoft Visual Studio (VS)2010 常用快捷键大全 便捷开发
  9. 程序基本功之遍历二叉树
  10. golang中的json