《2830.多线程下载工具的设计与实现论文.doc》由会员分享,可在线阅读,更多相关《2830.多线程下载工具的设计与实现论文.doc(24页珍藏版)》请在课桌文档上搜索。
1、简单多线程下载工具的设计与实现【摘要】随着互联网应用范围不断扩展,网络包含的信息资源日益增多。互联网用户可以通过网络下载所需的数据资源并保存到本地磁盘当中,因此相应的基于网络的下载工具应运而生。随着基于网络的多线程下载技术的出现,如今的下载工具已彻底摆脱了带宽瓶颈的束缚并且向着更为人性化的方向发展。本设计采用Java和多线程技术设计并实现了一个简单多线程下载工具。该工具可对指定的任务进行下载,同时支持断点续传功能。【关键字】java;多线程;断点续传;Swing目录1.引言31.1 开发背景31.2 开发意义32. 系统分析32.1 设计概述32.1.1 实现目标32.1.2 开发环境32.2
2、.开发相关技术简介32.2.1 Java语言简介32.2.2 多线程技术简介42.2.3 HTTP1.1协议42.2.4 断点续传的技术42.3 可行性分析42.3.1 技术可行性分析42.3.2 经济可行性分析52.3.3 操作可行性分析53. 概要设计53.1 系统结构图53.2 功能流程图54.详细设计64.1 获取网络资源64.1.1 功能说明64.1.2 设计说明64.1.3 核心代码74.2 线程任务分配84.2.1 功能说明84.2.2 设计说明84.2.3 设计流程84.3 创建下载任务94.4 任务下载104.4.1 功能说明104.4.2 设计说明104.4.3 核心流程1
3、14.5 事件监听器设计124.5.1 功能说明124.5.2 设计说明124.6 下载控制器设计124.6.1 功能说明134.6.2 设计说明134.6.3 功能流程144.7 显示控制器设计154.7.1 功能说明154.7.2 设计说明154.8 断点记录文件设计174.8.1 功能说明174.8.2 设计说明174.8.3 保存断点线程流程图184.9 文件操作184.9.1 功能说明184.9.2 设计说明184.9.3 文件操作流程194.10 GUI界面设计194.10.1 功能说明204.10.2 设计说明205. 设计问题总结215.1 断点设置问题215.2 下载速度统计
4、问题226. 参考文献资料221.引言1.1 开发背景随着互联网应用范围不断扩展,网络包含的信息资源日益增多,互联网用户可以通过网络下载所需的数据资源保存在本地磁盘当中,因此相应的基于网络的下载工具应运而生。对于一个网络下载工具,有两个问题一直阻碍着下载技术的发展:速度和下载后的管理。但是伴随着基于网络的多线程下载技术的出现,如今的下载工具彻底摆脱了这两个问题的束缚并且向着更为人性化的方面发展下去。1.2 开发意义本系统是开发一个简单的多线程下载工具,基本实现单资源的多线程任务下载,同时实现断点续传的功能。相对于目前主流下载工具的实现技术,本设计是不能相比的。实现这么一个下载具最大的意义是探索
5、多线程下载的基本原理,综合运用所学的知识,提高自己的动手能力,及查阅资料继续学习的能力。2. 系统分析2.1 设计概述对于这么一个多线程下载工具的设计,首先就是要设定好实现的目标,确定开发的环境。有个合理的设计目标使得在设计过程中不茫然,思路更清楚。而一个好的开发环境对提高开发的效率起着很重要的作用。2.1.1 实现目标实现一个实用的多任务,多线程下载工具。具备以下功能:1、 实现一个简洁的易操作的GUI界面2、 实现新建下载任务的功能3、 下载过程实现多任务,多线程的功能4、 实现任务暂停,及恢复下载的功能5、 实现停止任务功能2.1.2 开发环境Eclipse,windows xp,jre
6、,jdk2.2.开发相关技术简介本节将对本设计中用到的一些主要技术进行简单的介绍。2.2.1 Java语言简介Java是一种简单的、面向对象的、分布式的、解释型的、健壮安全的、结构中立的、可移植的、性能优异、多线程的语言,自1995年SUN推出JAVA语言后,全世界的目光都被这个神奇的语言所吸引。由于Java所具有的以上那些特性,所以我选用JAVA做为本设计的开发语言。2.2.2 多线程技术简介线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。在
7、本设计中,多线程的技术用在新建新任务和下载线程上,在系统中我们可以开始多个下载线程下载同一个网络上的资源而互不干扰。它从宏观上看是并行运行的,但对于微观上来说,它是却是串行运行的,线程的运行在操作系统的调度下,各自得到一定的时间片,当某一线程获取到时间片时,它就进入运行状态。各个线程按照一定的协议分别获取时间片。2.2.3 HTTP1.1协议HTTP1.1(Hypertext Transfer Protocol Vertion 1.1)超文本传输协议-版本1.1 。它是用来在Internet上传送超文本的传送协议。它是运行在TCP/IP协议族之上的HTTP应用协议,它可以使浏览器更加高效,使网
8、络传输减少。任何服务器除了包括HTML文件以外,还有一个HTTP驻留程序,用于响应用用户请求。您的浏览器是HTTP客户,向服务器发送请求,当浏览器中输入了一个开始文件或点击了一个超级链接时,浏览器就向服务器发送了HTTP请求,此请求被送往由IP地址指定的URL。驻留程序接收到请求,在进行必要的操作后回送所要求的文件。2.2.4 断点续传的技术在当今的网络时代,下载软件是使用最为频繁的软件之一。几年来,下载技术也在不停地发展。最原始的下载功能仅仅是个“下载过程”,即从WEB服务器上连续地读取文件。其最大的问题是,由于网络的不稳定性,一旦连接断开使得下载过程中断,就不得不全部从头再来一次。随后,“
9、断点续传”的概念就出来了,顾名思义,就是如果下载中断,在重新建立连接后,跳过已经下载的部分,而只下载还没有下载的部分。多线程下载的基础是WEB服务器支持远程的随机读取,也即支持“断点续传”。这样,在下载时可以把文件分成若干部分,每一部分创建一个下载线程进行下载。 不仅在关机或者网络出错的情况下这项技术。2.3 可行性分析可行性研究实质上是要进行一次大大压缩简化了的系统分析和设计的过程,也就是在较高层次上以较抽象的方式进行的系统分析和设计的过程。它的目的不是解决问题,而是确定问题是否值得去解决。2.3.1 技术可行性分析通过根据软件的需求,对本设计的技术实现进行全面的了解,可以采用java的多线
10、程机制,通过设置HTTP 1.1的请求头信息,可以实现连接远程资源的指定偏移位置,通过这个特性我们就可以实现多线程及断点续传的功能。所以根据目前已知的技术,在技术上实现多线程下载没有问题。2.3.2 经济可行性分析从开发这个简单多线程的意义上我们可以看出,赢利不是制作这个下载工具的目的,而只是为了单纯的探索多线程下载的基本原理,综合运用所学的知识,提高自己的动手能力,及查阅资料继续学习的能力。所以它也就不存在经济的问题。而从它的意义上来说,绝对值得制作这个下载工具。2.3.3 操作可行性分析由于这个多线程下载工具所面向的是广大的互联网用户,所以在设计中采用简洁的GUI界面。也因为简洁的界面设计
11、使得系统在操作方式上很容易让用户接受。在操作上对一没有计算机操作经验的人来说也不会有难度,因此在操作上也是行得通的。3. 概要设计3.1 系统结构图本系统采用现今比较流行的三层结构进行系统分层,这三层分别为GUI表现层,控制层,底层下载操作,文件及网络操作,系统的结构图如图3-1图 3-1 系统结构图3.2 功能流程图新建下载及恢复下载功能流程图见图3-2,在这里新建任务与恢复任务仅是在任务的构建方式上不一样,在网络操作及下载操作上都没有什么区别,这样的实现主要得益于对代码重用性的设计。图 3-2 新建/恢复任务流程图暂停与停止的功能实现流程图见图3-3,从这个图中我们可以发现和新建任务,恢复
12、任务一样具备同样的代码利用,停止线程过程是同一个,他们两个在功能上不同仅是暂停任务时我们需要将暂停的断点记录下来,而停止任务却是将断点记录给删除,并删除已下载的部分文件信息。图 3-3 暂停/停止任务流程图4.详细设计4.1 获取网络资源获取网络资源是下载过程中的第一个步骤,也是很关键的一步。由于网络的问题是多变的,有可能指定的下载资源已经不存在,或者网络连接有问题,等一系列的问题,因些在连接资源过程中我们得对于相应的连接进行相应在测试,它是否可行,它的信息是否是我们想要的,这一节主要就是讨论这个功能。4.1.1 功能说明要下载一个远程的资源就需我们能够先定位到指定的资源,并建立连接。在本模块
13、中实现的基本功能说是与远程的资源进行连接,并测试其连接状态。4.1.2 设计说明在做这个模块之前我们得先来了解下HTTP协议。HTTP协议就是超文件传输协议,采用了请求/响应模型。客户端向服务器发送一个请求,请求头包含请求的方法、URI、协议版本、以及包含请求修饰符、客户信息和内容的类似于MIME的消息结构。服务器以一个状态行作为响应,相应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。1、连接资源通过JDK的net包中包含的URL及HttpURLConnection两个类对网上资源进行操作。URL指定网络资源的位置,而HttpURLConnecti
14、on中则封装了操作指定网络资源的方法。在本系统中我设计了类ConnectionManager,它的主要功能就是通过提供指定的URL获取HttpURLConnection对象,为控制层代码利用HttpURLConnection对象操作网络文件提供支持。控制层代码只要调用ConnectionManager.getConnection(URL)即可。2、测试连接在网络连接过程中可能出现各种各样的问题,而我们需要的只是连接成功的正确网络资源,所以我们有必要对通过ConnectionManager获取的与服务器的连接进行测试。如果测试成功,即能正确获取到指定的资源,包括获取是否支持断点续传的功能,之后我
15、们才对指定的资源进行下载操作,否则抛弃信息,并对用户进行相应的提示。通过对HTTP1.1协议的了解,我们知道只要我们发送一个指定的请求头信息,服务器就会返回一个携带着请求后服务器处理完成的信息,这个信息就包括请求是否成功等。我们要做的就是构造这样一个带有指定的请求的头信息发送到服务器端,然后查看它返回的响应码,因为我们完成可能从响应码中去了解一个请求是否成功。要设计一个什么样的请求头才能符合我们的要求的测试效果呢?通过设计请求头信息中的RANGE字段我们可以指定请求URL指向目标资源的偏移量,而不是从头开始读。这个也是断点及多线程下载资源的一个重要属性,我们将在后面作更详细说明。如果我们设置完
16、这个头信息并发送到服务器端,如果源请求的资源存在并且服务器支持断点续传,这时它返回的响应码信息就是206,如果存在但不支持断点则返回200,而其它的情况就都是连接失败的情况了。这样测试连接的理论基础就完成了,那我们用net包的类怎么设置请求头信息,如何获取响应码信息呢?其实这些都是很容易的,代码如下:connection.setRequestProperty(RANGE,bytes=+0+-);设置请求头的RANGE字段int code = connection.getResponseCode();获取响应码信息到此,有关网络连接,及测试连接的设计就告一段落了。4.1.3 核心代码1、 获取连
17、接如果获取网络资源出错时则返回一个空值public static HttpURLConnection getConnection(URL url)HttpURLConnection huc = null;try huc = (HttpURLConnection)url.openConnection(); catch (Exception e) huc=null;throw new RuntimeException(连接资源错误+e.getMessage();finallyreturn huc;2、 测试连接private int testConnection(URL url)HttpURLCo
18、nnection connection = ConnectionManager.getConnection(url);int state = ConnectionManager.CONNECT_ERROR;/初始值为连接失败if(connection!=null)try /设置请求头,为了判断其是否支持服务器端随机读取connection.setRequestProperty(RANGE,bytes= + 0 + -);/获取响应信息String errorMessage = connection.getResponseMessage();/获取响应码int code = connection
19、.getResponseCode();switch(code)case 200:state = ConnectionManager.NO_BREAKPOINT_SUPPORT;break;case 206:state = ConnectionManager.BREAKPOINT_SUPPORT;break;default:state = ConnectionManager.CONNECT_ERROR;errorManager.addErrors(code,errorMessage); catch (Exception e) state = ConnectionManager.CONNECT_E
20、RROR;errorManager.addErrors(1000, 未知的主机地址,请检查网络连接或者下载URL地址n注:本系当前只运行HTTP下载);return state;4.2 线程任务分配我们通过对http1.1协议的了解后,知道通过对它的请求头进行设置,就可以获取到远程文件的指定部分,而不用从头开始下载。利用这个特性我们就可以设计一个多线程下载的原型出来了。要进行多线程下载,主要实现的是为每个线程分配一个指定范围的数据下载,那怎么为每一个下载线程进行任务分配呢?这就是这一节要讨论的内容。4.2.1 功能说明在多线程下载过程中,我们需要让每一个线程都指向指定资源的一部分,且不重复,如
21、何为每一个下载线程分配它指向的特定部分就是这个模块所要完成的任务。4.2.2 设计说明确定了采用分块的形式进行任务的分配,那我要考虑的问题就只有如何分块了,如何分配才能准备无误,并且保证各个下载线程所要下载的任务更合理。本系统采用的是平均分配的方法。就是为每一个下载线程分配尽可能相同的字节数,在这个过程中我们得指定下载任务相对于资源起点的偏移量及下载的长度。分配过程如下:1、 获取资源长度,这个可以从请求的响应信息中获取“Content-Length”字段获得,代码如下:connection.getHeaderField(Content-Length);2、 根据线程数计算各个任务块的偏移量及
22、下载长度,这个过程简单,但得注意字节重复的问题。4.2.3 设计流程图 4-1 任务分配流程图4.3 创建下载任务有了之前的一系列操作,我们就可以着手创建下载任务了,我将下载的任务封装成两个实体,Task和SubThread。Task用来保存下载任务的基本信息及状态信息,这些信息包括任务号、线程数、URL地址、文件名、文件保存路径、下载文件长度、任务状态、支持断点标志、已下载长度、完成标志。并在Task里面设计一个集合封装SubThread,封装每个下载子线程的下载信息详细请看图 。SubThread包括相对资源头的偏移量(startPosition)、要下载的长度(downFileLengt
23、h)、已下载的长度(downedFileLength)、下载完成标志(isComplete)、引用此子线程的实际下载线程,用于维护线程的状态(downThread)、还有一个事件监听器(event)用于监听本线程的下载情况,对于该监听器的说明将在后现进行描述。创建下载任务的时就是将Task及SubThread实例化并赋予指定资源统计得到的初始值的过程,这一步的正确执行是后面正确下载的基础。下图是Task 图4-2及SubThread 图4-3 的类图:图 4-2 任务实体类图图 4-3 子下载线程实体类图创建下载任务流程图:图 4-4 创建下载任务流程4.4 任务下载任务下载模块是本系统的核心
24、,在任务运行过程中主要的的时间也是在花这一块,它的设计质量,会对软件的效率,占用资源的大小,软件的可靠性及可用性有很大的影响。就拿软件的可用性来说,因为在系统的下载过程中,读取出来的长度是随机的,而且我们还要关心着本线程的下载范围,因此如果未对其中的各个细节进行考虑,很容易就会出现读脏数据的情况,导致最终下载过来的数据无法使用。4.4.1 功能说明创建完任务我们就可以开始进行下载操作了。在这个模块中,要使用线程技术实现一个可重用的,较高效的实现程序。主要功能就是能能读取出指定资源相应偏移量的数据,并调用文件操作模块将下载的数据保存到相应文件中去。4.4.2 设计说明本设计中设计了两个实现了Ru
25、nnable的线程类TaskThread,DownThread。TaskThread类的主要任务就是根据传递进来的任务实体进行分析,并开启指定数量的下载线程(DownThread)进行下载。TaskThread中我们需要完成这么几个步骤:1、 解析Task,获取下载的线程数2、 根据指定的下载线程数开启相应的线程3、 设置当前系统正在下载的任务数DownThread中我们需要完成这么几个步骤1、 获取在task中包装着的下载线程任务(SubThread)2、 设置SubThread中的DownThread为任务暂停及任务停止垫定基础3、 根据SubThread中的信息计算请求远程资源的偏移量4
26、、 设置的待下载信息设置HTTP请求头信息,请求指定的资源5、 获取网络流6、 读取系统配置中下载块大小的网络流保存至一个缓存中7、 保存至本地文件中,设置块下载完毕,这里会触发块下载完事件当线程下载完成时会设置SubThread的isComplete并触发子线程下载完毕的事件。4.4.3 核心流程1、 子线程下载流程图 4-5 子线程下载流程图2、 核心代码while(readBytes=is.read(buffer)!=-1&!stop)size+=readBytes;/记录已下载的字节数(未进行无效数据删减的)if(sizedownFileLength)readBytes=(int)(b
27、uffer.length-(size-downFileLength);flag=true;/设置下载范围完成标志/如果下载的长度大于要下载的长度减去多出来的部分,因为当前线程只要求下载固定长度的文件 subThread.setDownedFileLength(subThread.getDownedFileLength()+readBytes);fo.saveFile(savePosition,buffer,saveFilePath, readBytes);/保存缓存的数据到文件中去savePosition += readBytes;/设置保存偏移量task.setDownFileLength(
28、task.getDownFileLength()+readBytes);/设置当前任务的下载长度,用于下载进度和速度统计if(flag)break;if(!stop)subThread.setComplete(task, true);/设置线程下载完成,触发下载完成事件4.5 事件监听器设计事件机制在这个设计中非常的重要,所有关于线程下载完成,任务下载完成的时候都是通过事件被触发的方式完成。这种机制的好处就是不用开启新的线程去监视下载的情况,实时性上要比采用监视线程要好很多,在消耗的资源上也比开监视线程要小很多,仅在事件被触发时才进行相应的操作。4.5.1 功能说明在任务下载过程中,我们要进行
29、一系列的操作如:下载文件的保存,根据下载线程的完成情况判断文件是否下载完毕等,所以本系统中我设计了一个监听器用来监听事件的变化。在初始化任务和下载线程时为它们注册监听器,当并在事件处理代码中对相应的事件进行响应。事件处理机制在本设计中占有很大的比重。4.5.2 设计说明类图:图 4-6 事件监听及其它抽象实现类图4.6 下载控制器设计本设计基本上符合MVC的设计模式,而作为C的部分,也是系统的核心部分。系统中所有的命令都是通过下载控制器进行转发,而GUI界面也就是通过下载控制器与网络,本地文件之间进行操作,从而实现系统的一个个功能。4.6.1 功能说明下载控制器在本设计中处于核心的地位,所有来
30、自GUI界面的请求,还有底层网络操作及文件的操作都通过控制器进行协调工作。控制器在整个系统的运行周期中都存在着作用,在应用程序刚刚启动时,它需要读取系统配置及上一次下载的断点信息。所有对于下载的操作都要通过它来转发,甚至每一次断点的保存都是通过它完成。4.6.2 设计说明控制器继承自DownEventImpl,使得控制器类具备父类处理下载事件的能力。类图4-7:图 4-7 控制器设计与事件监听关系类图成员变量说明:tasks:用来保存当前统中维护着的所有下载任务的信息,新建任务时就往当中加入一个新的任务信息(Task task),暂停任务,停止任务,恢复任务同,移除已完成等操作都要从tasks
31、获取信息或者写入信息。taskNum:维护当前系统中正在进行下载的任务数量threadNum:当前系统中正在进行下载任务的下载线程(DownThread)数量config:系统的配置信息,在系统初始化时给config赋值errorManager:保存错误信息,当系统发生错误时,将往其中加入错误信息,集中处理异常。控制类的工作内容包括:1、 初始化系统初始化系统配置:本系统可以通过SystemConfig对系统默认的参数进行配置,并保存到一个配置文件当中去。所以在系统初始化时,控制器需要读取系统的配置信息,并维护在DownCotroller中的成员config中。为系统的使用提供更人性化的服务,
32、也使软件可配置,并在某些方面可以提高系统的性能,比如设置最小下载块尺寸。因为下载最小块的尺寸与文件保存及断点保存是相关联的,而对于文件操作它们耗费的资源是较多的,所以最小下载块的设计不能过小,当然也不能过大,如果过大,那么处理断点时就不够准确,总会丢失最后下载没有保存的断点。初始化断点:在系统初始化时需要将上次下载过程中保存的下载信息读到系统中来,并维护在tasks中,使我们可以在系统运行后可以对上次未完成或者已下载的信息进行我们想要完成的操作,比如继续下载,重新下载等。2、 接收GUI界面请求,由此操作网络操作这类中为了与GUI界面进行交互,它提供以下几个api:a. newTask(URl
33、 url,String filePath,int threadNum)用来创建新任务,如果创建成功就开始下载url:要下载的指定要下载的远程资源地址filePath:指定下载的文件要保存到的本地位置threadNum:指定要下载的文件的下载线程数在本方法中要完成的任务就是,测试远程连接地址,及它是否支持断点续传。成功后创建任务,并开启任务线程(TaskThread)开始下载。b. resumeTask(String taskNo)用来恢复暂停的任务taskNo是指定要恢复的任务号,通过这个任务号,从控制类中的tasks成员中获取到指定恢复下载的断点信息,测试连接,开启线程(TaskThread
34、)恢复从指定位置下载。c. haltTask(String taskNo)本成员方法用于暂停选定的任务根据taskNo从tasks中取出指定的任务,停止当前正在运行的下载线程,并登记断点,设置任务状态,将断点信息保存到文件中。d. removeTask(String taskNo)移除下载任务,它可以移除当前正在进行的任务,也可以移除已下载完成的任务。如果移除的是正在下载的任务里会给出提示,停止任务的下载线程,并将当前任务从task中移除,更新断点信息,删除已下载的文件片段,更新GUI任务列表的显示。如果移除的是已下载完成的任务,则会仅会从task中移除指定的任务记录信息,更新断点,更新GUI
35、任务列表的显示。e. removeComplete()移除已下载完毕的任务,当执行此方法时,程序将从task中取出相应的任务记录,f. 其它还有成员属性的getter,和setter。用于操作控制类的成员变量,设置当前系统任务数,线程数等。4.6.3 功能流程流程图:图 4-8 下载控制器功能描述 从流程图上我们可以看出,下载控制器主要功能是实现控制的转发。4.7 显示控制器设计显示控制设计主要是为了实现显示模型的统一,并对操作显示模型的操作进行代理,使得模块外对显示模型的操作透明,并加上一些附加的功能。4.7.1 功能说明用于控制下载主界面上各个信息的显示控制(主要是下载列表的显示)。对主页
36、面上下载列表的显示控制仅需调用DisplayController的方法进行操作,而不需要知道具体是如何操作显示。从某种意义上说这个类仅是一个操作显示的一个代理类。4.7.2 设计说明类图:图 4-9 下载控制器类图成员变量model是主显示界面中JTable的通过对model进行相应的操作即可更新主界面下载列表的显示。在讲述显示控制之前先了解下显示模型,和封装的行对象。自定义的显示模型ShowModel功能:使重JTable更好用,更符合我们的要求类图:图 4-10 JTable显示模型类图 各方法说明:1、 addRowData(Row row)将行数据保存到rowData中去2、 getC
37、olumnCount()获取当前模型中的列数3、 getColumnName(int column)获取模型定义的各列名称4、 getRowCount()查看rowData获取行数5、 getRowData()获取所有的行数据6、 isCellEditable()设置此表格是否允许编辑,本设计设置为不可编辑7、 removeData(Row row)移除某一行的数据,并调用reOrderRowNum()对所有的列表进行重排序8、 reOrderRowNum()对所有的行数据进行重排序,使删除不会导致因行标志获取错误面显示出错9、 SetValueAt(Object obj,int row,in
38、t column)设置某一单元格的值10、 updateRowData(Row row)更新一个行信息,当此行在显示模型中不存在时(根据任务号判断是否存在),则添加进rowData,如果已存在则对其更行替换。自定义的行对象Row功能:用于描述JTable的一行类图:图 4-11 显示行实体类图下面介绍DisplayController中的各个方法的功能:1、 addRowData(Row row)将行数据添加到显示模型中2、 deleteRowData(String taskNo)从显示模型中移除任务号为taskNo的任务3、 createRowData(Task task)根据传递进来的Ta
39、sk新建一个新的行4、 updateRowData(Task task)根据Task调用createRowData先创建一个新的Row对象,然后调用model的updateRowData(Row row)方法更新显示模型数据通过以上一系统的准备工作,我们基本上就可以了解这个类的控制方法了,无非就是对显示模型的操作进行了代理,使得模型对外透明,而我们只需要将其它模块本身熟悉的Task交给DisplayController就可以实现我们所要的显示效果。4.8 断点记录文件设计作为一个要实现断点续传功能的软件来说,一个断点记录的文件是必不可少的。而这个文件的实现技术多种多样。运用什么技术?如何设计一
40、个合理的断点保存机制对于本系统来说就变得尤为重要,怎么在系统中实现断点的记录?断点记录的是些什么信息?断点是保存在什么文件中?这都是这一节要考虑的问题。4.8.1 功能说明断点记录是实现断点续传中非常关键的一步,下载线程在下载过程中可能会出现各种各样的问题导致下载中断,设置断点保存就可以解决这个问题。但这些异常发生是随机的,未知的,这就给我们设置断点记录点发出了挑战,在本设计中实现了断点的定时记录,文件断点文件将被保存到XML文件当中,并确定了断点文件需要记录了些什么信息的功能。4.8.2 设计说明1.记录的都是些什么信息?1、 保存下载任务的基本信息:url、保存路径、下载线程数、任务号、下
41、载文件长度、文件名、是否支持断点续传、下载状态信息、平均下载速度、下载运行时间。2、 各个线程的线程号3、 各个线程下载的起始位置4、 各个线程下载的长度5、 各个线程已下载的长度2.断点记录保存到什么文件中?本设计是将断点信息保存到一个xml文件当中去,因为我们能够很容易操作xml文件,且使用xml文件保存在开发过程中很有用,我们可以通过查看xml文件中的信息就可以发现一些下载过程中遇到的问题。3.什么时候记录断点?下载过程中异常发生的随机性使得我们在记录断点时无法使用一个特定的时间来记录,所以这时如何设置记录断点的时机就变得非常的重要,怎么做才能够将尽可能多的数据准确的保存起来?为了提高系
42、统的运行效率,在本设计中,我采用定时保存断点的形式,每过1s就保存一次断点到文件中,同时更新显示。这个功能主要是在ShowThread中去实现的。4.8.3 保存断点线程流程图流程图:图 4-12 保存断点设计图4.9 文件操作本地文件的操作在设计中仅是实现了下载所需要的功能,其中包括对下载块的保存,下载完文件的更名操作。4.9.1 功能说明下载文件的操作是将下载线程从网络流中获取到的信息保存到指定目录下的文件当中去,并可对已下载的文件进行移动等相应的操作。4.9.2 设计说明对下载文件的操作,FileOperate文件操作,FileOperate的类图如下:图 4-13 文件操作类图1、 s
43、aveFile()用于将从下载线程传递过来的下载缓存信息写到指定的文件当中去downedPosition:指定对与当前的线程,它的已下载的位置,以使能够正确的将buffer里的数据保存到指定的文件位置中去。filePath:指定要保存到的文件路径readBytes指定下载线程在本次下载中写在buffer里的文件长度中包含有效的数据。2、 deleteFile(String filePath,int threadNum)用于删除已被系统删除的文件片段filePath: 指定要删除文件的路径threadNum:指定要删除任务的线程数,以此来计算得到每个文件片段的下载文件名mergeFile()用于
44、合并文件,因为下载过来的文件是为每个线程保存成一个独立的文件,所以在下载完成时需要合并这些文件。合并完成会删除各线程的临时文件段。4.9.3 文件操作流程文件保存操作流程图:图 4-14 文件操作流程图4.10 GUI界面设计GUI是图形用户接口的简称,设计一个简洁,易操作的用户图形化界面在软件设计过程中是非常重要的,它关系到软件的可用性,易用性的问题。4.10.1 功能说明GUI界面它是我们用户与应用程序进行交流的窗口,通它我们可以很方便的对程序进行控制操作。使用者并不需要具备专业的技术,只要轻轻点点鼠标就行。所以在制作GUI时我们要考虑到诸多的问题,如设计怎么样能更加符合用户的使用习惯等。
45、4.10.2 设计说明本下载工具有如下几个界面,分别完成不同的功能需要1. WDFrame这个是应用程序的主界面,当程序运行时显示就是这个页面,页面截图如下图 4-15 软件主界面2. 各菜单选项图 4-16 各菜单项3. 新建下载NewTask是新建下载任务,它可能通过系统的配置为用户默认的添加一些下载的基本信息,它是系统刚刚启用时所有下载流程的第一步,页面截图如下:图 4-17 新建任务界面 4. 系统配置SystemConfigFrame系统设置页面,用来对一些下载的基本参数进行配置,如果未配置则系统将调用一个默认的配置信息。页面如图4.11:图 4-18 系统配置界面5. 设计问题总结5.1 断点设置问题问题描述:在设计刚刚开始时,我仅在任务暂停,任务停止,以及关闭程序或者任务出现错误时才进行断点的保存,显然这不够合理,如果在下载过程中用户关闭计算机或突然断点,或者是在任务管理器中将任务终止,那么断点还没来得及保存到文件程序就关闭了,达不到我们的要求。修改设计:实现了一个显示的线程ShowThread.java,在显示线程中对每一次的刷新显示都对断点进行保存,这样使得断点保存以显示速率进行保存。本系统中是每隔一秒刷新一次,所以断点也是一秒钟保存一次。5.2 下载速度统计问题问题描述:原本系统通过采用开始时间及下载的长度来统计下载的进度及下载的速度,就是在任务开