多线程断点续传的FTP软件设计毕业论文.doc_第1页
多线程断点续传的FTP软件设计毕业论文.doc_第2页
多线程断点续传的FTP软件设计毕业论文.doc_第3页
多线程断点续传的FTP软件设计毕业论文.doc_第4页
多线程断点续传的FTP软件设计毕业论文.doc_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

目录摘要1Abstract1一前言2 (一)设计背景2 (二)设计内容2 (三)FTP的简介2 (四)FTP的工作原理3 (五)FTP的系统结构和功能描述31. FTP系统结构的一般过程32. Winsocket网络编程基础3二FTP多线程技术介绍4(一)FTP协议的介绍和一些基本命令4(二)如何从 FTP服务器上下载文件5(三)FTP多线程下载技术6(四)FTP多线程实例6三FTP多线程断点续传的实现以及编码7(一)实现方法7(二)工作流程7(三)服务器端代码的实现8(四)客户端代码的实现28结论30致谢30参考文献30支持多线程断点续传的FTP软件设计摘要 文件的传送功能是如今网络应用中的重要功能之一,是实现共享的前提条件。但现今的网络还很不稳定,要想单纯靠FTP来传送大量的数据,有可能会因为网络不稳定而半途而废,本论文是在VC+基础上编写支持断点续传的FTP软件,其中涉及服务器与客户端的链接,文件保存方式的技巧,线程任务划分和同步运行,友好界面的设计等很多匠心独运的设计技巧,实现不稳定网络中单、多线程断点续传数据,并对单、多线程断点续传输数据的性能结合运行结果进行有效的比较和分析。并在现有的FTP软件的基础上提出了对其进行改进的方法,有效提高数据传输的可靠性和高效性,对当今网络中的数据传输具有一定的意义。关键字 断点续传;FTP;服务器;客户端;多线程下载Support breakpoint continuingly FTP software designAbstract File transfer function is now one of the important function of network applications, is the precondition of sharing.But now, the network is not stable, want to be sent by simple FTP data, because the network may be unstable and halfway, this paper is based on vc + + written in support breakpoint continuingly FTP server software, including links with the client, file save mode skills, thread task division and synchronization operation, friendly interface design, the design skill alone many instability in the network realization, multithreading breakpoint continuingly data, and the single, multi-thread download data transfer performance effectively combined operation results compared and analyzed.And in the existing FTP software is put forward on the basis of the improvement of the method of data transmission, effectively improve the reliability and efficiency of the current network data transmission has certain significance.Key words Breakpoint continuingly; FTP; Server; The client; Multithreaded downloads1引言 随着计算机技术和网络技术的发展,FTP服务已是当前网络的重要应用之一3,FTP服务器为客户提供文件上传和文件下载服务,而当今讨论和应用较多的是FTP的下载续传技术,对于上传的技术则涉及的较少。越来越多的网络应用和网络协议需要用到并支持断点续传的功能,即由于网络不稳定造成的文件传输终止,下次能够从上次终止的地方开始接着传送,避免重复下载数据,提高了数据的有效性和传输的高效性。为了满足新的通信需求,研究人员已开发了许多新的协议和算法。而在已有的协议(如FTP)基础上增强协议的功能是可行且有效的方法,多线程断点续传的设计和实现可以强大FTP的功能,更高效的实现大量数据的传送。1.1设计背景文件传输协议(FTP)作为网络共享文件有效的传输协议,在网络应用软件中具有广泛的应用,在很多场合可以满足网络用户对共享数据、有效与可靠传输的需求4,5。 FTP是FileTransfer Protocol(文件传输协议)的缩写,用来在两台计算机或异构网络间互相传送文件。相比其他协议(如:HTTP),FTP协议要复杂得多,FTP协议要用到两个TCP连接,一个是命令链路,用来在FTP客户端和服务器间传送命令;另一个是数据链路,用来上传和下载各种格式的数据。FTP使用客户服务器方式1,2。与一般的Client/Server应用最大的不同点在于:一般的Client/Server应用程序只会在服务器端和客户端建立一个Socket连接,此连接同时处理服务器端和客户端的连接以及数据的传输;而FTP协议则不同,在服务器端和客户端共建两个Socket连接,一个是以FTP协议默认的端口21作为两者之间的通信连接,另一个连接则作为客户端传输指令和服务器端响应结果用15。一个FTP服务器可同时为多个客户进程提供服务。FTP服务器进程由两大部分组成:一个是主进程负责接收客户端发来的请求;另外有若干个从属进程负责处理单个的请求。FTP软件断点续传指的是文件上传或下载时,将上传或下载的任务划分为几个部分。每个部分采用一个线程同步进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分继续上传或下载后面的没有完成的部分,而没有必要重头开始上传或下载。这样可以节省时间,提高速度。有时用户上传或下载数据要历时数小时,一旦连接中断,不具备断点续传的FTP服务器或下载软件就只能重头开始上传或下载;比较好的服务器或下载软件应该具备断点续传的能力,这样大大减少了用户的烦恼17。利用多线程实现的支持断点续传的FTP软件正是这样的一种好的服务器,在网络中的应用会越来越广泛。1.2 设计内容FTP文件传输服务器系统是在VC开发环境下、基于C/S模式、使用当前模块化软件设计思想编程实现的。在服务器设计时先总体设计服务器系统的整体模型,之后再分别设计前台的控制界面和后台服务器的框架。然后使用Windows平台上通用的客户端软件和设计编写的测试软件对此信息传输服务进行测试,并对测试结果进行分析8,10。断点续传文件保存的方法是产生两个文件:内容文件和配置文件。FTP多线程下载技术部分是将一个要下载的文件用几个线程来完成,即将文件分成几个子模块,但并不是把文件的内容存放到对应的几个不同缓冲区里,而是生成几个不同的偏移量。 1.3 FTP简介FILE TRANSFER PROTOCOL(FTP)意为文件传输协议,用于管理计算机之间的文件传送。FTP 通常指文件传输服务。 FTP 是 Internet 上使用非常广泛的一种通讯协议。它是由支持 Internet 文件传输的各种规则所组成的集合,这些规则使 Internet 用户可以把文件从一个主机拷贝到另一个主机上,因而为用户提供了极大的方便和收益。FTP 和其它 Internet 服务一样,也是采用客户机/服务器方式。使用方法很简单,启动FTP 客户端程序先与远程主机建立连接,然后向远程主机发出传输命令,远程主机在收到命令后就给予响应,并执行正确的命令。FTP 有一个根本的限制,那就是,如果用户未被某一FTP 主机授权,就不能访问该主机,实际上是用户不能远程登录(Remote Login)进入该主机。也就是说,如果用户在某个主机上没有注册获得授权,没有用户名和口令,就不能与该主机进行文件的传输。而 Anonymous FTP(匿名 FTP)则取消了这种限制。FTP 协议与操作系统无关,任何操作系统上的程序只要符合 FTP 协议,均可以互相传送数据。 FTP 应用在 TCP/IP 网络体系结构中位于应用层,所使用的 FTP 协议在网络协议栈中位于 TCP 层之上,属于一种应用层协议, 1.4 的工作原理开发任何一种基于的客户端软件都必须遵循的工作原理,的独特优势同时也是与其他客户服务器程序最大的不同点在于它在两台通信的主机间使用了两条连接,一条是数据连接,用于传送数据;另一条是控制连接,用于传送控制信息16。这种将数据和命令分开传送的思想大大提高了的效率,而其他客户服务器应用程序一般只有一条连接13。图给出了的基本模型。客户由三个构件:用户接口,客户控制进程和客户数据传送进程。服务器有两个构件:服务器控制进程和服务器数据传送进程12。在整个交互的会话中,控制连接始终是处于连接状态,数据连接则在每一次文件传送时先打开后关闭。用户接口数据传送进程控制进程数据传送进程控制进程 文件传输客户服务器图的基本模型1.5 FTP的系统结构和功能描述1.5.1 FTP系统结构的一般过程目前的FTP客户端软件很多,在功能上,一般都具有文件的上传、下载、在服务器上创建或删除目录和文件的功能20。这里不再继续类似FTP客户端软件的开发,而是采用一种新的FTP客户端软件,称为FTP文件信息采集系统,该系统的功能主要有:(1) FTP主机信息自动发现,就是能搜索和寻找任意指定网段内匿名的FTP服务器,将匿名FTP服务器的IP地址以列表的形式报告给用户,可以帮助用户最大限度的利用互联网上FTP提供的公共信息资源;(2) FTP文件信息的采集,在搜索匿名的FTP服务器主机信息的同时,系统将采集服务器内的文件信息列表,也可以利用用户名和密码登录指定的非匿名的FTP服务器搜索采集服务器内的文件信息;(3) FTP文件信息的过滤,系统根据文件名关键字、修改时间以及文件大小提供三种不同的过滤机制,同时可以设定文件类型分类整理相应的文件,从而达到满足不同用户的需求。整个文件信息采集系统结构。 系统控制和管理模块 包括本系统的升级和维护;搜索策略的配置;采集结果获取等功能。 搜索采集执行模块 搜索采集文件站点信息和FTP服务器状态信息,并负责进行各模块之间的信息交换,解释执行系统控制和管理模块的配置。 站点文件信息生成模块 负责读取搜索采集程序的执行结果,将其采集到的文件信息存放到指定的数据库中,并可根据不同文件类型生成相应的报告,满足不同用户需求。 FTP主机信息生成模块 负责读取搜索采集程序的执行结果,将有关远程FTP服务器的状态信息存放在相应的数据库中。 文件搜索过滤模块 采用三种搜索过滤机制对文件进行过滤筛选,分别是基于文件修改时间、基于文件名关键字和基于文件大小的过滤技术。1.5.2 Winsocket网络编程基础 Windows下的FTP传输是基于SOCKET之上。FTP在IS0的OSI网络七层协议中,Winsocket主要负责控制数据的输入和输出,也就是传输层和网络层18。Winsocket屏蔽了数据链路层和物理层,给Windows下的网络编程带来了巨大的方便。Winsocket编程分为服务器模型及客户端模型。下面以客户端为例子说明使用步骤:1)调用WSAStartup()初始化Winsocket;2)然后调用socket()创建一个会话socket;3)再调用connect()与server端连接;4)调用send()和recev()进行对话;5)调用closesocket()关闭socket19。二 FTP协议实现多线程断点续传 (一)FTP协议的介绍和一些基本命令FTP下载的好处就不赘述了,许多工程会把FTP下载作为一个重要功能来实现。微软提供的WinInet类可以利用下面这些函数:InternetOpen;InternetConnect;GetCurrentDirectory;SetCurrentDirectory;FtpGetFile;很容易实现FTP的下载,但是要实现FTP的多线程下载,利用这些函数还远远不够。用socket根据FTP协议来开发将会变得十分灵活。下面我就逐步的讲解整个开发的过程:开发环境 BCB(组件模式),VC 环境下稍作改动。首先介绍一下部分FTP协议:用户用户接口文件系统服务器PI服务器 DTPUser PI用户DTP文件系统 FTP服务示意图用户FTP和服务器FTP之间要传送文件,需要有两个连接:命令通道和数据连接,从名字上就可以看出命令通道是传送命令的,数据通道是用于传送文件。主要用到的命令为:USER,PASS,TYPE,SIZE,REST,CWD,PWD,RETR,PASV,PORT,QUIT; USER:参数是标记用户的Telnet串。用户标记是访问服务器必须的,此命令通常是控制连接后第一个发出的命令,有些主机还会要求口令和帐户。服务器可以在任何时间接收新的USER命令以改变访问控制和(或)帐户信息。这可以重新开始登录过程,所以传输参数不变,在进行中的文件传输在过去的访问控制参数下完成。 PASS:参数是标记用户口令的Telnet串。此命令紧跟USER命令,在某些站点它是完成访问控制不可缺少的一步。因此口令是个重要的东西,因此不能显示出来,服务器方没有办法隐藏口令,所以这一任务得由用户FTP进程完成。 TYPE:参数指定表示类型。有些类型需要第二个参数,第一个参数由单个Telnet字符定义,第二个参数是十进制整数指定字节大小,参数间以分隔。下面是格式:图二TYPE参数示意图默认表示类型是ASCII非打印字符,如果参数未改变,以后只改变了第一个参数,则使用默认值。 SIZE:参数从FTP服务器上返回指定文件的大小。 REST:参数域代表服务器要重新开始的那一点,此命令并不传送文件,而是略过指定点后的数据,此命令后应该跟其它要求文件传输的FTP命令。 CWD:此命令使用户可以在不同的目录或数据集下工作而不用改变它的登录或帐户信息。传输参数也不变。参数一般是目录名或与系统相关的文件集合。 PWD:改变当前的工作目录。 RETR:开始传送指定的文件。(从REST参数指定的偏移量开始传送) PASV:此命令要求服务器DTP在指定的数据端口侦听,进入被动接收请求的状态,参数是主机和端口地址。 PORT:参数是要使用的数据连接端口,通常情况下对此不需要命令响应。如果使用此命令时,要发送32位的IP地址和16位的TCP端口号。上面的信息以8位为一组,逗号间隔十进制传输。 QUIT:退出登录。 (二) 如何从 FTP服务器上下载文件 FTP 服务端和客户端之间存在两中连接:一中用于传输 FTP 命令(命令必须由客户端主动发起),连接始终存在;另一中用于向客户端传输数据,每当要传输文件或目录文件列表信息时则建立一个数据连接,数据传输完毕立即断开。 数据连接有两种建立方式: PORT 和 PASV。PORT 方式下,客户端监听某端口,服务器主动发起数据连接。PASV 方式下,服务器监听某端口,客户端主动发起数据连接。客户端可分别向服务器发送 PORT 或 PASV 命令指定连接模式。 下载文件之前首先需要登陆。登陆成功后,发送 TYPE 设定数据传输格式(字符格式还是二进制方式),然后发送PORT 或 PASV 选择数据传输方式。得到成功响应或,根据返回信息与服务器建立数据连接。如果前面发送的命令均得到成功响应,则开始发送下列请求,告诉服务器准备数据。首 先发送 REST 命令(如有需要),指定开始下载的偏移量;然后发送 REST 命令指定要下载的文件。 如果前面发送的命令均得到成功响应,则表示服务器数据准备完毕。下面需要做的是与服务建立数据连接,开始接受数据,并将接收到的数据保存在本地文件中,直到接收完毕后断开数据连接,下载完毕。(三) FTP多线程下载技术 完登陆操作后,先发送“REST 100”命令,测试下服务器是否支持断点下载,如返回成功代码,就可实现多线程下载;然后发送“SIZE”,取得文件的大小,根据文件大小,将文件分为几部分,记下各部分的偏移地址,并作为参数,交给各线程去下载。在下载线程中,先接受主线程传给他的参数(文件名,偏移地址,保存地址等),再发送“PASV”命令,建立数据连接,并新建一套接字连接到新的端口;然后根据文件类型,二进制文件发送“TYPE I“命令,文本文件发送”TYPE A“命令;之后发送“REST 文件偏移地址”命令,通知服务器改变将要下载的文件的开始地址;最后,执行“RETR 文件名”命令,下载文件。下载完毕后,编段代码合并文件即可。在这里有个问题,就是主线程如何得知各下载线程已执行完毕。WINDOWS提供了几种线程互斥技术,如CriticalSection,Mutex等,关于他们的详细信息,大家可参考各种编程书籍,在这里我推荐使用CriticalSection技术。可以在程序中建立一全局计数器,在文件下载前置零,并建立一全局CriticalSection变量。在下载线程中,当文件下载完毕后,先锁定全局CriticalSection变量,之后将计数器加一,再释放全局CriticalSection变量。主线程中,可建立一定时,定期检查计数器的值,或让下载线程在下载完毕后调用主线程的某个函数。这样,主线程就可随时发现文件已下载完毕,可合并文件了。(四)FTP多线程下载实例现在有个noname.avi文件需要下载。文件的大小为:364544字节。要用个下载线程。 第一步:将noname.avi文件分成个子模块。这里所说的分成个子模块,并不是把文件的内容分别存放到个不同的缓冲区里。而是生成个不同的文件偏移量。很多时候程序员为了偷懒往往容易一次性讲文件读入内存,这样带来的后果是不堪设想的。一个比较理想的方法是这样的。 bool DealFile(string fileName) /随便写个函数说明 FILE *file; DWORD fileSize ,pos; int readLen ; /MAX_BUFFER_LEN 在头文件里定义,这里能够保证数据不丢失,也不至于内存逸出 char *buffer = new charMAX_BUFFER_LEN; file = fopen(fileName.c_str(),r+b); if(file = NULL) return false; fseek(file,0,2); fileSize = ftell(file); /取得文件的大小 fseek(file,0,0); do readLen = fread(buffer,sizeof(char),MAX_BUFFER_LEN,file); if(readLen 0) pos += readLen; /对读取的文件做处理 while(pos fileSize); /循环读取文件 delete buffer; fclose(file); /释放资源 return true;8个线程下载文件时,都要对内容文件和配置文件进行读写。这样如果没有处理好,很有可能会造成访问文件失败,我定义了一个全局变量FileLocked,如果FileLocked=true说明文件正在被某个线程访问。所以使用Sleep(10)睡眠等待。当某个线程进入读写文件时必须设置FileLocked = true;访问文件完毕必须将FileLocked = false;这样就能很好的控制各个线程对文件的访问了。 8个下载线程同时下载文件时,完成部分下载是随机的。把随机的文件数据按照偏移量正确的写入文件的实现是这样的,当要下载文件noname.avi时,首先查找文件noname.avi.san配置文件是否存在。如果存在,说明上次已经下载过部分该文件,就可以断点续传了。如果没有找到该文件,那么生成和该文件的大小一样大的文件,文件里所有的数据都为0,(可以使用函数memset(buffer,10000,0))和一个配置文件。然后利用fseek函数将数据正确的覆盖原先的0。 各个线程任务分配是这样实现的。在开始下载时,文件平均分成若干块进行下载。如第一个线程一开始的任务是从文件的0位置开始下载一直到72908位置处。线程1每次下载一块数据后就要调整任务,如第一次下载了20800字节的数据,那么线程1的任务将改为:20800-72908。如此下去,直到任务为72908-72908时表示线程1完成了当前的下载任务。此时,线程1就分析各个线程的任务,找出任务最为繁忙的一个线程:如线程3:14816-218724。那么线程1就自动去调整任务,拿50%的任务来再次下载。周而复始直到各个线程都完成任务。不过这里有一点需要注意:为了避免重复下载部分数据,在调整任务的时候,起始的文件偏移量必须加上接受缓冲器的字节数,因为如前面所举的列子来看。线程1和线程3在平衡负载的时候,线程正在下载数据,如果所剩的数据比接受缓冲器的大小还小,线程1和线程3的部分下载数据将会重复。 在调整任务和分析任务的时候,会发现一个问题。就是读取文件数据太过频繁。于是用了一个数据结构。在下载文件的过程中始终打开配置文件,这样速度提高了很多。在文件下载完毕后关闭文件。数据结构如下: typedef struct FromToImpl DWORD from; /任务起始位置 DWORD to; /任务结束位置 m_fromTo; typedef struct InfroImpl String fileLoad; /文件保存位置 DWORD fileSize; /文件大小 int threadCnt; /下载线程数 DWORD alreadyDownloadCnt; /已经下载的文件大小 FromToImpl *fromToImpl; /各个线程的任务描述m_inforImpl;三 FTP多线程断点续传的实现以及编码3.1 实现方法仍采用服务器与客户模式,需分别对其设计与编程。运用VC+编程语言,基于TCP/IP协议服务器端较简单,主要就是加入待传文件,监听客户,和传送文件。而那些断点续传的功能,以及文件的管理都放在客户端上。3.2 FTP工作流程FTP典型工作流程如下:(1)客户端创建socket;(2)客户端连接FTP服务器;(3)客户端发送命令到FTP服务器;(4)客户端接收FTP服务的返回信息;(5)客户端发送PORT命令请求建立数据链接;(6)客户端连接FTP服务器返回的IP及端口;(7)客户端发送数据到服务器;(8)客户端发QUIT结束会话。3.3 服务器端代码实现一、首先介绍服务器端:最开始我们要定义一个简单的协议,也就是定义一个服务器端与客户端听得懂的语言。而为了把问题简化,就让服务器只要听懂两句话,一就是客户说“请求读文件信息”,二就是“准备好了,可以传文件了”。由于要实现多线程,必须把功能独立出来,且包装成线程,首先建一个监听线程,主要负责接入客户,并启动另一个客户线程。用VC+实现如下:DWORD WINAPI listenthread(LPVOID lpparam) /由主函数传来的套接字 SOCKET pthis=(SOCKET)lpparam; /开始监听 int rc=listen(pthis,30); /如果错就显示信息if(rcSendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1); aaa.ReleaseBuffer(); return 0; /进入循环,并接收到来的套接字 while(1) /新建一个套接字,用于客户端 SOCKET s1; s1=accept(pthis,NULL,NULL); /给主函数发有人联入消息 CString aa; aa=一人联入!n; AfxGetMainWnd()-SendMessageToDescendants(WM_AGE1,(LPARAM)aa.GetBuffer(0),1); aa.ReleaseBuffer(); DWORD dwthread; /建立用户线程 :CreateThread(NULL,0,clientthread,(LPVOID)s1,0,&dwthread); return 0;接着来看用户线程:先看文件消息类定义:struct fileinfo int fileno;/文件号 int type;/客户端想说什么(前面那两句话,用1,2表示) long len;/文件长度 int seek;/文件开始位置,用于多线程 char name100;/文件名;用户线程函数: DWORD WINAPI clientthread(LPVOID lpparam) /文件消息 fileinfo* fiinfo; /接收缓存 char* m_buf; m_buf=new char100; /监听函数传来的用户套接字 SOCKET pthis=(SOCKET)lpparam; /读传来的信息 int aa=readn(pthis,m_buf,100); /如果有错就返回 if(aatype) /我要读文件信息 case 0: /读文件 aa=sendn(pthis,(char*)zmfile,1080); /有错 if(aaSendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1); break; /我准备好了,可以传文件了 case 2: /发文件消息给主函数aaa.Format(%s 文件被请求!%sn,,namephfiinfo-fileno); AfxGetMainWnd()-SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1); /读文件,并传送 readfile(pthis,fiinfo-seek,fiinfo-len,fiinfo-fileno); /听不懂你说什么 default: aaa=接收协议错误!n; AfxGetMainWnd()-SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1); break; return 0;读文件函数 void readfile(SOCKET so,int seek,int len,int fino) /文件名 CString myname; myname.Format(%s,namephfino); CFile myFile; /打开文件 myFile.Open(myname, CFile:modeRead | CFile:typeBinary|CFile:shareDenyNone); /传到指定位置 myFile.Seek(seek,CFile:begin); char m_bufSIZE; int len2; int len1; len1=len; /开始接收,直到发完整个文件 while(len10) len2=lenSIZE?SIZE:len; myFile.Read(m_buf, len2); int aa=sendn(so,m_buf,len2); if(aa0) closesocket (so); break; len1=len1-aa; len=len-aa; myFile.Close();3.4 客户端代码实现 客户端最重要,也最复杂,它负责线程的管理,进度的记录等工作。大概流程如下:先连接服务器,接着发送命令1(给我文件信息),其中包括文件长度,名字等,然后根据长度决定分几个线程下载,并初使化下载进程,接着发送命令2(可以给我传文件了),并记录文件进程。最后,收尾。这其中有一个十分重要的类,就是cdownload类,定义如下: class cdownload public: void createthread();/开线程 DWORD finish1();/完成线程 int sendlist();/发命令1 downinfo doinfo;/文件信息(与服务器定义一样) int startask(int n);开始传文件n long m_index; BOOL goodBLACK; int filerange100; CString fname; CString fnametwo; UINT threadfunc(long index);/下载进程 int sendrequest(int n);/发文件信息 cdownload(int thno1); virtual cdownload();下面先介绍sendrequest(int n),在开始前,向服务器发获得文件消息命令,以便让客户端知道有哪些文件可传 int cdownload:sendrequest(int n) /建套接字 sockaddr_in local;SOCKET m_socket; int rc=0; /初使化服务器地址 local.sin_family=AF_INET; local.sin_port=htons(1028); local.sin_addr.S_un.S_addr=inet_addr(ip); m_socket=socket(AF_INET,SOCK_STREAM,0); int ret; /联接服务器 ret=connect(m_socket,(LPSOCKADDR)&local,sizeof(local); /有错的话 if(ret0) AfxMessageBox(联接错误); closesocket(m_socket); return -1; /初始化命令 fileinfo fileinfo1; fileinfo1.len=n; fileinfo1.seek=50; fileinfo1.type=1; /发送命令 int aa=sendn(m_socket,(char*)&fileinfo1,100); if(aa0) closesocket(m_socket); return -1; /接收服务器传来的信息 aa=readn(m_socket,(char*)&fileinfo1,100); if(aastartask(clno);/建立各线程createthread(clno);下面介绍开始方法: /开始方法int cdownload:startask(int n) /读入文件长度 doinfo.filelen=zmfilen.length; /读入名字 fname=; CString tmep; /初使化文件名 tmep.Format(temp%s,fname); /给主函数发消息 CString aaa; aaa=正在读取 +fname+ 信息,马上开始下载。n; AfxGetMainWnd()-SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1); aaa.ReleaseBuffer(); /如果文件长度小于0就返回 if(doinfo.filelen=0) return -1; /建一个以.down结尾的文件记录文件信息 CString m_temp; m_temp=fname+.down; =m_temp; FILE* fp=NULL; CFile myfile; /如果是第一次下载文件,初使化各记录文件 if(fp=fopen(m_temp,r)=NULL) filerange0=0; /文件分块 for(int i=0;i0) filerangei*2=i*(doinfo.filelen/BLACK+1); filerangei*2+1=doinfo.filelen/BLACK+1; filerangeBLACK*2-1=doinfo.filelen-filerangeBLACK*2-2; myfile.Open(m_temp,CFile:modeCreate|CFile:modeWrite | CFile:typeBinary); /写入文件长度 myfile.Write(&doinfo.filelen,sizeof(int); myfile.Close(); CString temp; for(int ii=0;iim_work.m_ListCtrl-AddItemtwo(n,2,0,0,0,doinfo.threadno); else /如果文件已存在,说明是续传,读上次信息 CString temp; m_temp=fname+.down0; if(fp=fopen(m_temp,r)=NULL) return 1; else fclose(fp); int bb; bb=0; /读各进程记录的信息 for(int ii=0;iim_work.m_ListCtrl-AddItemtwo(n,2,doinfo.totle,1,0,doinfo.threadno); /建立下载结束进程timethread,以管现各进程结束时间。 DWORD dwthread; :CreateThread(NULL,0,timethread,(LPVOID)this,0,&dwthread); return 0;下面介绍建立各进程函数,很简单: void CMainFrame:createthread(int threadno) DWORD dwthread; /建立BLACK个进程 for(int i=0;im_index); /执行下载进程 pthis-threadfunc(pthis-m_index-1); return 1;下面介绍下载进程函数,最最核心的东西了 UINT cdownload:threadfunc(long index) /初使化联接 sockaddr_in local; SOCKET m_socket; int rc=0; local.sin_family=AF_INET; local.sin_port=htons(1028); local.sin_addr.S_un.S_addr=inet_addr(ip); m_socket=socket(AF_INET,SOCK_STREAM,0); int ret; /读入缓存 char* m_buf=new charSIZE; int re,len2; fileinfo fileinfo1; /联接 ret=connect(m_socket,(LPSOCKADDR)&local,sizeof(local); /读入各进程的下载信息 fileinfo1.len=filerangeindex*2+1; fi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论