`
yidongkaifa
  • 浏览: 4063694 次
文章分类
社区版块
存档分类
最新评论

c++实现文件传输之三:断点续传与多线程传输转

 
阅读更多

继木马编程DIY的上两篇,现在我们开始讨论断点续传与多线程文件传输的实现.其实这两项功能是下载软件所
必不可少的功能了,现在我们把它加到自己的木马中来感受感受.提到多线程下载,首先向网络蚂蚁的作者
洪以容前辈致敬,正是由于网络蚂蚁而使得多线程下载被关注并流行起来.在这本篇文章中我们将简单的实现
支持断点续传和多线程传输的程序.为了更清晰的说明问题,我们将断点续传与多线程传输分别用两个程序来实现

多线程传输实现
实现原理
将源文件按长度为分为N块文件,然后开辟N个线程,每个线程传输一块,最后合并所有线线程文件.比如
一个文件500M我们按长度可以分5个线程传输.第一线程从0-100M,第二线程从100M-200M......最后合并5个线程文件.
实现流程
1.客户端向服务端请求文件信息(名称,长度)
2.客户端跟据文件长度开辟N个线程连接服务端
3.服务端开辟新的线程与客户端通信并传输文件
4.客户端将每线程数据保存到一个文件
5.合并所有线程文件
编码实现
大体说来就是按以上步骤进行,详细的实现和一些要点,我们跟据以上流程在编码中实现

结构定义
在通信过程中需要传递的信息包括文件名称,文件长度,文件偏移,操作指令等信息,为了方便操作我们定义如下结构

代码:
typedef struct
{
char Name[100]; //文件名称
int FileLen; //文件长度
int CMD; //操作指令
int seek; //线程开始位置
SOCKET sockid;
}FILEINFO;
1.请求文件信息
客户端代码如下

代码:
FILEINFO fi;
memset((char*)&fi,0,sizeof(fi));
fi.CMD=1; //得到文件信息
if(send(client,(char*)&fi,sizeof(fi),0)==SOCKET_ERROR)
{
cout<<"Send Get FileInfo Error\n";
}
服务端代码如下
while(true)
{
SOCKET client;
if(client=accept(server,(sockaddr *)&clientaddr,&len))
{
FILEINFO RecvFileInfo;
memset((char*)&RecvFileInfo,0,sizeof(RecvFileInfo));
if(recv(client,(char*)&RecvFileInfo,sizeof(RecvFileInfo),0)==SOCKET_ERROR)
{
cout<<"The Clinet Socket is Closed\n";
break;
}else
{
EnterCriticalSection(&CS); //进入临界区
memcpy((char*)&TempFileInfo,(char*)&RecvFileInfo,sizeof(RecvFileInfo));
switch(TempFileInfo.CMD)
{
case 1:
GetInfoProc (client);
break;
case 2:
TempFileInfo.sockid=client;
CreateThread(NULL,NULL,GetFileProc,NULL,NULL,NULL);
break;
}
LeaveCriticalSection(&CS); //离开临界区
}
}
}
在这里服务端循环接受连接,并跟据TempFileInfo.CMD来判断客户端的请求类型,1为请求文件信息,2为下载文件
因为在下载文件的请求中,需要开辟新的线程,并传递文件偏移和文件大小等信息,所以需要对线程同步.这里使用临界区
其文件信息函数GetInfoProc代码如下

代码:
DWORD GetInfoProc(SOCKET client)
{
CFile file;
if(file.Open(FileName,CFile::modeRead|CFile::typeBinary))
{
int FileLen=file.GetLength();
if(send(client,(char*)&FileLen,sizeof(FileLen),0)==SOCKET_ERROR)
{
cout<< "Send FileLen Error\n";
}else
{
cout<< "The Filelen is "<<FileLen<<"\n\n";
}
}
return 0;
}
这里主要是向客户端传递文件长度,而客户端收到长度后则开辟线程进行连接传输文件
2.客户端跟据长度开辟线程
其实现代码如下

代码:
FILEINFO FI;
int FileLen=0;
if(recv(client,(char*)&FileLen,sizeof(FileLen),0)==SOCKET_ERROR)//接受文件长度
{
cout<<"Recv FileLen Error\n";
}else
{
cout<<"FileLen is "<<FileLen<<"\n";
int COUNT_SIZE=FileLen/5; //每线程传输大小
for(int i=0;i<5;i++) //分5个线程传输
{
EnterCriticalSection(&CS); //进入临界区
memset((char*)&FI,0,sizeof(FI));
FI.CMD=2; //请求下载文件
FI.seek=i*COUNT_SIZE; //线程文件偏移
if(i+1==5) //最后一线程长度为总长度减前4个线程长度
{
FI.FileLen=FileLen-COUNT_SIZE*i;
}else
{
FI.FileLen=COUNT_SIZE;
}
Thread=CreateThread(NULL,NULL,GetFileThread,&i,NULL,NULL);
Sleep(500);
LeaveCriticalSection(&CS); //离开临界区
}
}
WaitForMultipleObjects(5,Thread,true,INFINITE); //等所有线程结束
这里默认开辟5个线程传输,当然可以改为想要的线程数目,仍然用临界区来实现线程的同步问题
3.服务端开辟线程传输数据
在1.请求文件信息中以说明了服务端的结构,这里主要介绍线程函数的实现,其代码如下

代码:
DWORD WINAPI GetFileProc(LPVOID lparam)
{
EnterCriticalSection(&CS); //进入临界区
int FileLen=TempFileInfo.FileLen;
int Seek=TempFileInfo.seek;
SOCKET client=TempFileInfo.sockid;
LeaveCriticalSection(&CS); //离开临界区
CFile file;
if(file.Open(FileName,CFile::modeRead|CFile::typeBinary))
{
file.Seek(Seek,CFile::begin); //指针移至偏移位置
char *date=new char[FileLen];
int nLeft=FileLen;
int idx=0;
file.Read(date,FileLen);
while(nLeft>0)
{
int ret=send(client,&date[idx],nLeft,0);
if(ret==SOCKET_ERROR)
{
cout<<"Send Date Error \n";
break;
}
nLeft-=ret;
idx+=ret;
}
file.Close();
delete[] date;
}else
{
cout<<"open the file error\n";
}
closesocket(client);
return 0;
}
还是比较简单的,主要是获取线程的文件长度和偏移,并移动文件指针到偏移处,最后读取发送数据,而客户端
接受数据并写入文件.

4.客户端将线程数据保存到文件
GetFileThread的实现代码如下

代码:
DWORD WINAPI GetFileThread(LPVOID lparam)
{
char TempName[MAX_PATH];
sprintf(TempName,"TempFile%d",*(DWORD*)lparam); //每线程的文件名为"TempName"+线程数
SOCKET client;
SOCKADDR_IN serveraddr;
int port=5555;
client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(port);
serveraddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
if(connect(client,(SOCKADDR*)&serveraddr,sizeof(serveraddr))==INVALID_SOCKET)
{
cout<<"Connect Server Error\n";
}
EnterCriticalSection(&CS); //进入临界区
if(send(client,(char*)&FI,sizeof(FI),0)==SOCKET_ERROR)
{
cout<<"Send GetFile Error\n";
return 0;
}
CFile file;
int FileLen=FI.FileLen; //文件长度
int Seek=FI.seek; //文件偏移
LeaveCriticalSection(&CS); //离开临界区
if(file.Open(TempName,CFile::modeWrite|CFile::typeBinary|CFile::modeCreate))
{
char *date = new char[FileLen];
int nLeft=FileLen;
int idx=0;
while(nLeft>0)
{
int ret=recv(client,&date[idx],nLeft,0);
if(ret==SOCKET_ERROR)
{
cout<<"Recv Date Error";
break;
}
idx+=ret;
nLeft-=ret;
}
file.Write(date,FileLen);
file.Close();
delete[] date;
}else
{
cout<<"Create File Error\n";
}
return 0;
}
在此线程函数中,将每线程传输的数据存为一个文件,文件名为"TempName"+线程数,只所以存成单独的文件是
因为比较直观且容易理解,但如果文件很大的话这个方法并不好,因为合并文件又会花费很多时间,另一个方法
是 创始一个文件,让每个线程写入文件的不同偏移,这样就可以不必单独合并文件了,但要记得打开文件时
加入CFile::shareDenyNone属性.这样整个过程就完成了.最后一步合并线程文件
5.合并线程文件

代码:
int UniteFile() //合并线程文件
{
cout<<"Now is Unite Fileing...\n";
int len;
char *date;
CFile file;
CFile file0;
/*其它文件......*/
if(file.Open(FileName,CFile::modeCreate|CFile::typeBinary|CFile::modeWrite))//创建文件
{
file0.Open("TempFile0",CFile::modeRead|CFile::typeBinary);//合并第一线程文件
len=file0.GetLength();
date=new char[len];
file0.Read(date,len);
file.SeekToEnd();
file.Write(date,len);
file1.Open("TempFile1",CFile::modeRead|CFile::typeBinary);//合并第二线程文件
len=file1.GetLength();
date=new char[len];
file1.Read(date,len);
file.SeekToEnd();
file.Write(date,len);
/*合并其它线程......*/

file0.Close();
file1.Close();
/*.......*/
delete[] date;

return true;
}else
{
return false;
}
}
这个简单,就是打开一个文件读取到缓冲区,写入文件,再打开第二个......现在多线程传输部分就介绍完了
下面讨论断断点续传的实现

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhengkangchen/archive/2009/02/27/3942252.aspx

分享到:
评论

相关推荐

    c++实现文件传输之三:断点续传与多线程传输转.doc

    c++实现文件传输之三:断点续传与多线程传输转.doc c++实现文件传输之三:断点续传与多线程传输转.doc c++实现文件传输之三:断点续传与多线程传输转.doc c++实现文件传输之三:断点续传与多线程传输转.doc c++实现...

    TCP文件传输系统(Version 1.6 多线程,断点续传,支持大文件传输)

    采用Visual C++ 6.0开发的一个TCP文件传输系统,采用多线程的传输方式,支持断点续传,利用配置文件设置基本的初始化信息。 文件包括源代码和安装包,源代码里包括自定义的文件传输通信协议。 程序采用分层的设计...

    TCP文件传输系统 (多线程,支持断点续传,VC)

    采用Visual C++ 6.0开发的一个TCP文件传输系统,采用多线程的传输方式,支持断点续传,利用配置文件设置基本的初始化信息。 文件包括源代码和安装包,源代码里包括自定义的文件传输通信协议。 程序采用分层的设计...

    断点续传和多线程下载,可实现大文件传输

    断点续传和多线程下载,可实现大文件传输.断点续传和多线程下载,可实现大文件传输.

    多线程文件传输V2.2 支持断点续传 收发消息 点对多点 完整源代码(C/C++)

    完整源代码版本2.2 C/C++实现,包括完整源代码,vc工程文件,保证能够...支持断点续传. 服务端可同时接收多个文件. 传输文件的同时可以发送网络消息. 用户界面与后台线程交互 如有问题请与我联系: hongxing777@gmail.com

    TCP文件传输系统(多线程,支持断点续传,VC)

    vc 下 实现 多线程 文件传输 系统,支持断点续传 功能

    C++_p2p实现多线程文件传输

    笔者一直想寻求一种简 单有效,且具备多线程断点续传的方法来实现点与点之间的文件传送问题,经过大量的翻阅资料与测试,终于实现了,现把它共享出来,与大家分享。 我写了一个以此为基础的实用程序(网络传圣,包含...

    C/C++多线程文件传输v2.2完整源码(断点续传 网络消息收发 高效率 界面与后台线程交互)

    多线程socket文件传输/支持断点续传/收发消息/点对多点 使用阻塞方式的socket,使用多线程,有较高的性能. 在局域网中测试达到极限速度. 支持断点续传. 服务端可同时接收多个文件. 传输文件的同时可以发送网络消息. ...

    Http/FTP多线程断点续传下载组件

    多线程传输:可以将文件自动分块,并采用多线程下载。并可自由设置线程数目。 断点续传:点量Http/FTP有优秀的断点续传支持,每次启动自动从上次下载的位置开始,不需要重复下载。 提供详细的下载详情接口(2.0...

    C C++ Linux多线程文件程序

    基于linux下的c/c++程序,多线程,断点续传功能没有实现, 可传输大于2G的文件。 设计思想:预先分配的N个缓冲区形成类似循环队列。 【1】预先分配N个缓冲区,多线程方式对缓冲区进行读写互斥,有类似生产者消费者的...

    CC++多线程文件传输v2.2完整源码(断点续传 网络消息收发 高效率 界面与后台线程交互).rar

    CC++多线程文件传输v2.2完整源码(断点续传 网络消息收发 高效率 界面与后台线程交互)

    点量Http/FTP多线程断点续传下载组件DLL

    点量Http、FTP多线程断点续传下载组件(下载DLL)的开发目的是让用户可以无需关心Http/FTP协议的具体细节,只需要几十行甚至几行代码,便可以实现一个功能完善的Http/FTP下载软件。点量Http/FTP下载组件(DLL)支持...

    大文件socket通讯传输

    基于linux下的c/c++程序,多线程,断点续传功能没有实现, 可传输大于2G的文件。 设计思想:预先分配的N个缓冲区形成类似循环队列。 【1】预先分配N个缓冲区,多线程方式对缓冲区进行读写互斥,有类似生产者消费者的...

    iclient:C ++封装libcurl,实现的http客户端,支持http(s)请求,支持下载文件(断点续传和分片下载)

    文件下载(普通下载,断点续传,分片下载) 限制下载/上传速度 2.关键命名空间与类 命名空间ic : 命名空间http 枚举Method :GET / POST / HEAD / ... 枚举StatusCode :HTTP状态码 枚举Version :V1_0 / V1_1

    文件传输系统

    用c++语言编写一个文件传输系统。功能是支持断点续传和多线程下载。

    vc++ 开发实例源码包

    FTP、HTTP 多线程断点续传下载文件 源码 如题。 gdiplus应用实例 如题,自绘控件的实现。 gdiplus应用实例2 如题,自绘控件的实现。 GetFileVersion 这个例子就是查询任何可执行文件的版本信息并且 C++builder 和...

    vc++ 应用源码包_6

    点对点多线程断点续传软件《传圣》源代码 多任务多线程断点续传DLL 多线程文件下载 多线程查找文件(功能增强版) 自定义了一个文件搜索类。多线程实现。 多线程高速文件搜索程序源码 VC++视频聊天系统源代码 实例...

    基于C++&QT实现的实验室管理系统源码+项目说明(高分毕设).zip

    - 多线程下载,断点传输 可以同时下载多个文件,一开始是用TCP + 本地SQLite数据库实现,正常使用是没什么问题,但是如果客户端突然挂掉就不好记录断点。后面通过读取文件大小再计算断点发给服务端,后续计划换成...

    vc++ 应用源码包_1

    点对点多线程断点续传软件《传圣》源代码 多任务多线程断点续传DLL 多线程文件下载 多线程查找文件(功能增强版) 自定义了一个文件搜索类。多线程实现。 多线程高速文件搜索程序源码 VC++视频聊天系统源代码 实例...

    vc++ 应用源码包_2

    点对点多线程断点续传软件《传圣》源代码 多任务多线程断点续传DLL 多线程文件下载 多线程查找文件(功能增强版) 自定义了一个文件搜索类。多线程实现。 多线程高速文件搜索程序源码 VC++视频聊天系统源代码 实例...

Global site tag (gtag.js) - Google Analytics