网络编程——断点续传和多线程下载模式

本文介绍了如何在C++ Builder中实现一个支持断点续传和多线程下载的下载模块。首先,文章阐述了下载技术的发展,包括从最初的单一下载到断点续传和多线程下载的演变。接着,详细讲解了HTTP协议的基础知识,以及WinInet API在下载过程中的应用。通过创建THttpGetThread线程模块,实现了连接建立、文件信息获取、下载文件及资源释放等步骤。在断点续传方面,通过检查本地已下载文件的大小,调整文件指针以实现续传功能。最后,讨论了如何在多线程环境下进行下载,包括线程的创建、管理以及文件的合并。整个过程涉及到了线程同步和文件处理等多个技术要点。
摘要由CSDN通过智能技术生成

概述

    在当今的网络时代,下载软件是使用最为频繁的软件之一。几年来,下载技术也在不停地发展。最原始的下载功能仅仅是个“下载”过程,即从WEB服务器上连续地读取文件。其最大的问题是,由于网络的不稳定性,一旦连接断开使得下载过程中断,就不得不全部从头再来一次。

    随后,“断点续传”的概念就出来了,顾名思义,就是如果下载中断,在重新建立连接后,跳过已经下载的部分,而只下载还没有下载的部分。
无 论“多线程下载”技术是否洪以容先生的发明,洪以容使得这项技术得到前所未有的关注是不争的事实。在“网络蚂蚁”软件流行开后,许多下载软件也都纷纷效 仿,是否具?quot;多线程下载"技术、甚至能支持多少个下载线程都成了人们评测下载软件的要素。"多线程下载"的基础是WEB服务器支持远程的随机读 取,也即支持"断点续传"。这样,在下载时可以把文件分成若干部分,每一部分创建一个下载线程进行下载。

    现在,不要说编写专门的下 载软件,在自己编写的软件中,加入下载功能有时也非常必要。如让自己的软件支持自动在线升级,或者在软件中自动下载新的数据进行数据更新,这都是很有用、 而且很实用的功能。本文的主题即怎样编写一个支持"断点续传"和"多线程"的下载模块。当然,下载的过程非常复杂,在一篇文章中难以全部阐明,所以,与下 载过程关系不直接的部分基本上都忽略了,如异常处理和网络错误处理等,敬请各位读者注意。我使用的开发环境是C++ Builder 5.0,使用其他开发环境或者编程语言的朋友请自行作适当修改。

HTTP协议简介

    下载文件是电脑与WEB服务器交互的过程,它们交互的"语言"的专业名称是协议。传送文件的协议有多种,最常用的是HTTP(超文本传输协议)和FTP(文件传送协议),我采用的是HTTP。

    HTTP 协议最基本的命令只有三条:Get、Post和Head。Get从WEB服务器请求一个特定的对象,比如HTML页面或者一个文件,WEB服务器通过一个 Socket连接发送此对象作为响应;Head命令使服务器给出此对象的基本描述,比如对象的类型、大小和更新时间。Post命令用于向WEB服务器发送 数据,通常使把信息发送给一个单独的应用程序,经处理生成动态的结果返回给浏览器。下载即是通过Get命令实现。

基本的下载过程

     编写下载程序,可以直接使用Socket函数,但是这要求开发人员理解、熟悉TCP/IP协议。为了简化Internet客户端软件的开发, Windows提供了一套WinInet API,对常用的网络协议进行了封装,把开发Internet软件的门槛大大降低了。我们需要使用的WinInet API函数如图1所示,调用顺序基本上是从上到下,其具体的函数原型请参考MSDN。

 在使用这些函数时,必须严格区分它们使用的句柄。这些句柄的类型是一样的,都是HINTERNET,但是作用不同,这一点非常让人迷惑。按照这些句柄的产生顺序和调用关系,可以分为三个级别,下一级的句柄由上一级的句柄得到。

    InternetOpen是最先调用的函数,它返回的HINTERNET句柄级别最高,我习惯定义为hSession,即会话句柄。

    InternetConnect使用hSession句柄,返回的是http连接句柄,我把它定义为hConnect。

    HttpOpenRequest使用hConnect句柄,返回的句柄是http请求句柄,定义为hRequest。

    HttpSendRequest、HttpQueryInfo、InternetSetFilePointer和InternetReadFile都使用HttpOpenRequest返回的句柄,即hRequest。

    当这几个句柄不再使用是,应该用函数InternetCloseHandle把它关闭,以释放其占用的资源。

    首先建立一个名为THttpGetThread、创建后自动挂起的线程模块,我希望线程在完成后自动销毁,所以在构造函数中设置:

FreeOnTerminate = True; // 自动删除

    并增加以下成员变量:

char Buffer[HTTPGET_BUFFER_MAX+4]; // 数据缓冲区
AnsiString FURL; // 下载对象的URL
AnsiString FOutFileName; // 保存的路径和名称
HINTERNET FhSession; // 会话句柄
HINTERNET FhConnect; // http连接句柄
HINTERNET FhRequest; // http请求句柄
bool FSuccess; // 下载是否成功
int iFileHandle; // 输出文件的句柄

1、建立连接

     按照功能划分,下载过程可以分为4部分,即建立连接、读取待下载文件的信息并分析、下载文件和释放占用的资源。建立连接的函数如下,其中ParseURL 的作用是从下载URL地址中取得主机名称和下载的文件的WEB路径,DoOnStatusText用于输出当前的状态:

//初始化下载环境
void THttpGetThread::StartHttpGet(void)
{
   AnsiString HostName,FileName;
   ParseURL(HostName, FileName);
   try
   {
      // 1.建立会话
      FhSession = InternetOpen("http-get-demo",
            INTERNET_OPEN_TYPE_PRECONFIG,
            NULL,NULL,
            0); // 同步方式
      if( FhSession==NULL)throw(Exception("Error:InterOpen"));
      DoOnStatusText("ok:InterOpen");
      // 2.建立连接
      FhConnect=InternetConnect(FhSession,
            HostName.c_str(),
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,NULL,
            INTERNET_SERVICE_HTTP, 0, 0);
      if(FhConnect==NULL)throw(Exception("Error:InternetConnect"));
      DoOnStatusText("ok:InternetConnect");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值