ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:20.19KB ,
资源ID:24030877      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/24030877.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(点对点P2P多线程断点续传的实现.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

点对点P2P多线程断点续传的实现.docx

1、点对点P2P多线程断点续传的实现点对点(P2P)多线程断点续传的实现在如今的网络应用中,文件的传送是重要的功能之一,也是共享的基础。一些重要的协议像HTTP,FTP等都支持文件的传送。尤其是FTP,它的全称就是“文件传送协议”,当 初的工程师设计这一协议就是为了解决网络间的文件传送问题,而且以其稳定,高速,简单而一直保持着很大的生命力。作为一个程序员,使用这些现有的协议传送文件相当简单,不过,它们只适用于服务器模式中。这样,当我们想在点与点之间传送文件就不适用了或相当麻烦,有一种大刀小用的意味。笔者一直想寻求一种简单有效,且具备多线程断点续传的方法来实现点与点之间的文件传送问题,经过大量的翻阅

2、资料与测试,终于实现了,现把它共享出来,与大家分享。我写了一个以此为基础的实用程序(网络传圣,包含源代码),可用了基于TCP/IP的电脑上,供大家学习。upload/2004_06/04062118541204.gif(本文源代码运行效果图) 实现方法(VC,基于TCP/IP协议)如下:仍釆用服务器与客户模式,需分别对其设计与编程。服务器端较简单,主要就是加入待传文件,监听客户,和传送文件。而那些断点续传的功能,以及文件的管理都放在客户端上。一、服务器端首先介绍服务器端:最开始我们要定义一个简单的协议,也就是定义一个服务器端与客户端听得懂的语言。而为了把问题简化,我就让服务器只要听懂两句话,一

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.Releas

4、eBuffer(); 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)s

5、1,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

6、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,zmfilefiinfo-fileno.name,

7、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

8、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(l

9、en10) 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();服务器端最要的功能各技术就是这些,下面介绍客户端。二、客户端客户端最重要,也最复杂,它负责线程的管理,进度的记录等工作。大概流程如下:先连接服务器,接着发送命令1(给我文件信息),其中包括文件长度,名字等,然后根据长度决定分几个线程下载,并初使化下载进程,接着发送命令2(可以给我传文

10、件了),并记录文件进程。最后,收尾。这其中有一个十分重要的类,就是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(lo

11、ng 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); loca

12、l.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;

13、/发送命令 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=zmfilen.nam

14、e; 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+

15、.down; doinfo.name=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:

16、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; e

17、lse 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)

18、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_

19、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; fileinfo1.seek=filerangeindex*2; fileinfo1.type=2; fileinfo1.fileno=doi

20、nfo.threadno; re=fileinfo1.len; /打开文件 CFile destFile; FILE* fp=NULL; /是第一次传的话 if(fp=fopen(fname,r)=NULL) destFile.Open(fname, CFile:modeCreate|CFile:modeWrite | CFile:typeBinary|CFile:shareDenyNone); else /如果文件存在,是续传 destFile.Open(fname,CFile:modeWrite | CFile:typeBinary|CFile:shareDenyNone); /文件指针移

21、到指定位置 destFile.Seek(filerangeindex*2,CFile:begin); /发消息给服务器,可以传文件了 sendn(m_socket,(char*)&fileinfo1,100); CFile myfile; CString temp; temp.Format(.down%d,index); m_temp=fname+temp; /当各段长度还不为0时 while(re0) len2=reSIZE?SIZE:re; /读各段内容 int len1=readn(m_socket,m_buf,len2); /有错的话 if(len10) closesocket(m_s

22、ocket); break; /写入文件 destFile.Write(m_buf, len1); /更改记录进度信息 filerangeindex*2+1-=len1; filerangeindex*2+=len1; /移动记录文件指针到头 myfile.Seek(0,CFile:begin); /写入记录进度 myfile.Write(&filerangeindex*2,sizeof(int); myfile.Write(&filerangeindex*2+1,sizeof(int); /减去这次读的长度 re=re-len1; /加文件长度 doinfo.totle=doinfo.totle+len1; ; /这块下载完成,收尾 myfile.Close(); destFile.Close(); delete m_buf; shutdown(m_socket,2); if(re=0) goodindex=TRUE; return 1;到这客户端的主要模块和机制已基本介绍完。希望好好体会一下这种多线程断点续传的方法。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1