基于SOCKET的多线程下载工具的开发

2011-06-13 12:53周学威闫鑫赵榉云杨薇
电子测试 2011年8期
关键词:线程消息编程

周学威,闫鑫,赵榉云,杨薇

(中北大学 仪器科学与动态测试教育部重点实验室,山西 太原 030051)

0 引言

多线程就是允许单个程序创建多个并行执行的线程来完成各自的任务,它在多任务和实时处理等方面具有重要意义,特别是在网络应用程序中,可以提高带宽利用率和程序反应速度[1]。为了达到下载大型网站的目的,在编写离线浏览软件的过程中,需要下载大量的Web文件,其中一个技术要点就是多线程下载问题。是否具有“多线程下载”技术、甚至能支持多少个下载线程都成了人们评测下载软件的要素[2]。本文以SOCKET技术为依托,基于VC++6.0环境,采用HTTP协议,通过编写客户端应用程序,对文件的多线程下载进行了设计与实现。

1 设计思路

多线程下载的前提是网络的连通和通信软件与协议的应用。下载文件的过程是客户端与服务器的交互的过程,在下载过程中采用的传送文件的协议有多种,本程序的设计采用了HTTP协议[3]。

HTTP即超文本传输协议,当客户端与服务器建立一个TCP连接后,客户端就可以发送请求并读取服务器的消息响应。在网络通信环境下,Socket作为应用程序和网络之间的标准接口,可以看成在两个程序进行通讯连接中的一个端点,是连接应用程序和网络驱动程序的桥梁[4]。

MFC是VC编程环境最重要的组成部分,它为用户提供了一大批预先定义的类和成员函数,封装了大量的Windows API[5]。为了简化套接字网络编程,更方便的利用Windows系统的消息驱动机制,充分利用MFC的优势,本设计采用基于MFC对话框的架构。

由于本设计基于HTTP协议,采用MFC WinSock中的CSocket套接字类进行编程,由客户端直接发送请求到服务器端进行资源的下载,因此只需编写客户端网络应用程序[6]。首先,根据HTTP协议,构造请求消息头,向Web服务器发送资源下载请求,当服务器返回请求成功后,再分别为每个线程构造下载请求,通过CSocket编程向服务器传输请求,实现各个线程的下载;然后,启动线程函数,包括四个下载线程用以实现多线程下载和一个监听线程来实时记录下载状态;最后当各个下载线程都结束时,进行文件合并,同时删除临时文件以完成下载任务[7]。

2 具体实现及主要函数

2.1 函数实现过程

实现过程可概括为:利用Socket套接字发送消息,在发送的消息中要构造请求消息字段,用HTTP协议向服务器发送下载请求,通过服务器的返回指令,实现资源下载,并通过启动线程函数来加入多线程技术,从而实现数据的多线程下载。其函数调用过程如图1所示。

要实现下载,必须由客户端向服务器发送请求消息,这是HTTP的核心。如图1所示,开始下载后,首先要获得要下载文件的URL,接着调用ParseURL函数判断要下载文件的URL是否合理,若合理,则会由SendRequest()函数向主线程发送HTTP请求消息,在调用GetInfo函数获取HTTP服务器成功响应的消息后,会为每个下载线程分配要下载的字节数。这样,开始下载任务成功实现后,会调用CDownloadDlg类中的CreateThread()函数中,创建线程,DownloadThread (LPVOID lpParam)是新建线程的入口函数,ThreadFunc(index)函数主要进行下载过程中每个子线程的套接字编程,通过编写向服务器发送请求消息的标题字段的代码,利用HTTP协议的下载原理实现每个子线程的下载。

图1 多线程下载的函数调用过程

2.2 主要函数说明

(1)创建下载线程,指向DownloadThread()这个线程函数的入口:

m_hThread[i]=::CreateThread(NULL, 0, DownloadThread,(LPVOID)&http, 0, &dwThread);

(2)创建监听线程,指向监听线程Notify()函数的入口,用以对各线程的下载状态和进度进行监听:

m_hNotify=::CreateThread(NULL,0,Notify,(LPVOID)this,0,&dwNotify);

(3)DownloadThread()函数:

DWORD WINAPI DownloadThread

(LPVOID lpParam);该函数会通过公有的继承方式继承ThreadFunc(index)函数,ThreadFunc(index)函数实现的主要功能是:每个子线程向服务器发送HTTP请求消息,实现每个子线程下载任务的完成。

(4)Notify()函数

DWORD WINAPI Notify(LPVOID lpParam);该函数中,会通过公有的继承方式继承在类CDownloadDlg中的Finish()函数,判断每个子线程是否完成下载,并进行下载文件的保存。

(5)ThreadFunc()函数

在ThreadFunc函数中,先要创建客户端的套接字对象,对每个要下载的子线程,设置了HTTP会话中的请求消息字段,通过由客户端向服务器发送请求消息实现每个子线程的下载。对于多线程下载,在请求消息的标题字段增加了Range,用于请求服务器返回指定大小的字段,其大小采用了数据分片技术来确定[8]。编写的语句为strRange.Format("Range: bytes=%d-%d ", m_state.range[2 * index], m_state.range[2 * index + 1]),其中index是线程的序列号。

3 系统运行

程序设计完成后,编译并运行,在生成对话框后,选择要下载文件的URL,将其直接拖入GetList列表控件中,点击开始按钮,开始下载。下载过程如图2所示,可见4个线程同步运行,实现了4个线程下载同一文件的多线程下载;下载完成时,弹出提示窗口提示“多线程下载完成”,如图3所示。此时单击提示窗口中的“确定”按钮,4个.jpg临时文件将合并成一个JPEG图像,至此便完成了多线程文件的下载。

图2 正在下载界面

图3 下载完成界面

4 结束语

本文对多线程数据传输进行了详细分析和总体设计,对多线程下载的原理、具体实现和应用进行了探讨,采用了面向对象的设计方法,应用多线程技术,通过Windows套接字函数,直接向Web服务器发送请求,用VC++6.0 MFC中的CSocket类编写客户端程序,实现了基于超文本传输协议HTTP的文件下载,通过创建和编写线程函数实现了多线程传输,经测试,下载速度有一定的改善。

[1]郑阿奇.Visual C++实用教程[M].3版.北京:电子工业出版社,2008.

[2]毛光喜.多线程下载工具的开发与应用[J].计算机应用与软件,2006,23(7):136-138.

[3]Charles Wright.VisualC++程序员使用大全[M].邓劲生,张晓明 译.北京:中国水利水电出版社,2001.

[4]蒋东兴.WindowsSockets网络程序设计大全[M].北京:清华大学出版社,1999.

[5]李晶媛.基于HTTP协议的多线程下载工具的实现[J].电脑开发与应用,2009,22(10):52-54.

[6]孙鑫,余安萍.VC++深入详解[M].北京:电子工业出版社,2007.

[7]赵辉,叶子青.VisualC++系统开发实例精粹[M].3版.北京:人民邮电出版社,2006.

[8]孙辉霞.基于VC++的多线程编程实现[J].中国电子商务,2010(3):61-62.

猜你喜欢
线程消息编程
基于C#线程实验探究
编程,是一种态度
元征X-431实测:奔驰发动机编程
编程小能手
纺织机上诞生的编程
一张图看5G消息
基于国产化环境的线程池模型研究与实现
浅谈linux多线程协作
消息
消息