C++实现文件传输.docx

上传人:b****8 文档编号:28089857 上传时间:2023-07-08 格式:DOCX 页数:13 大小:19.86KB
下载 相关 举报
C++实现文件传输.docx_第1页
第1页 / 共13页
C++实现文件传输.docx_第2页
第2页 / 共13页
C++实现文件传输.docx_第3页
第3页 / 共13页
C++实现文件传输.docx_第4页
第4页 / 共13页
C++实现文件传输.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

C++实现文件传输.docx

《C++实现文件传输.docx》由会员分享,可在线阅读,更多相关《C++实现文件传输.docx(13页珍藏版)》请在冰豆网上搜索。

C++实现文件传输.docx

C++实现文件传输

在木马中文件管理的重要性,是无需质疑的,对于文件的管理,做到并不难,但做好却也不易在我们编写一个功能完整的“文件木马”

其实现效果如图所示。

为了文章的完整性,我们将分为数篇来介绍,本文主要介绍程序的整体框架和界面实现,在以后的文章中将以此框架为基础实现详细的功能。

实现:

枚举磁盘,枚举目录,获取文件信息

上传文件,下载文件,执行文件,创建目录,删除目录等

传输控制结构

要实现客户端与服务端的通信,设计一个合理的传输控制结构,会使后面的工作轻松很多,为了使代码易读

首先对要使用的命令进行预定义其各个命令定义如下

#defineGetDriver0x01务端循环接受连接,并把连接交给线程处理

2.线程接受"命令数据",并跟据命令ID将命令对像和SOCKET句柄传给处理函数

3.函数执行指定功能,并返回执行结果

对整体结构的描述,我们用伪代码表述如下

main()

{/*初示化设置......*/

while(true)

{

if(client=accept(server,(sockaddr*)&clientaddr,&len))....*/

WSACleanup();

}

服务端程序运行后循环接受连接,如果有新的连接就传递给新的线程处理,线程代码如下

DWORDWINAPISLisen(LPVOIDlparam)

{

SOCKETclient=(SOCKET)lparam;

COMMANDcommand;

while

(1)

{

if(recv(client,(char*)&command,sizeof(command),0)==SOCKET_ERROR)....*/

}

}

}

}

线程式的功能是接受客户端的"命令数据",并跟跟据命令ID将命令对像传递给处理函数,由函数完成指定的功能

以删除文件命令为例其函数格式如下

DWORDDelFileProc(COMMANDcommand,SOCKETclient)

{

if(DeleteFile((char*)==0).");

}

else

{

send(client,"删除成功...");

}

}

很容易看出,处理函数接受"命令对像"和客户端SOCKET句柄,执行后会把结果传递回去....

客户端结构

客户端结构的实现思路如下

1.跟服务端建立连接

2.发送用户命令

3.启动一个线程,用于接受服务端的返回信息

对整体结构的描述,我们用伪代码表述如下

voidCMyDlg:

:

OnConnect()

if(connect(server,(SOCKADDR*)&serveraddr,sizeof(serveraddr))<0)..

{

return;

}

CreateThread(NULL,NULL,CLisen,this,NULL,NULL);

界面实现

程序的主界面如上图所示,主程序是一个对话框,主要包括一个树控件m_tree和列表控件m_list分别

用于显示磁盘目录和文件,在对话框初示化时用以下代码设置树控件的属性

DWORDdwStyle=GetWindowLong,GWL_STYLE);

dwStyle|=TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT;

SetWindowLong,GWL_STYLE,dwStyle);

对于列表框控件则没有太多要求,要留意的是,如果显示图标应该把Styles显示属性设置为ICON

VC的做出的界面,常常让人有种摔键盘的冲动。

其实稍微留意一下其设置,也可以让它漂亮一些

比如上图所示的界面就是经过简单设置得到的,而没有用其它类库,有点兴趣?

其设置方法为:

1.在对话框属性中设置Styles的Border属性为Thin

2.选重MoreStyles"可见"属性

3.选重ExtendedStyles的"静态边"属性

这样再运行一下程序是不是感觉清新不少?

到这里程序的主要结构框架和界面实现就介绍完了,下一篇将详细介绍其各种功能的实现

c++实现文件传输之二

在上一篇中,我们以经介绍了程序的流程和框架,在本篇将详细讨论各个功能的实现主要包括

1.获取磁盘信息

2.获取目录信息

3.获取文件信息

4.运行指定文件

5.删除指定文件

6.删除指定目录

7.创建指定目录

8.上传下载文件

9.获取远程文件图标

获取磁盘信息

磁盘信息可以用APIGetDriveType来实现,它以路径名作为参数(如C:

/)返回磁盘类型,其实例代码如下

DWORDGetDriverProc(COMMANDcommand,SOCKETclient)

{

for(chari='A';i<='Z';i++)

{

charx[20]={i,':

'};

UINTType=GetDriveType(x);

if(Type==DRIVE_FIXED||Type==DRIVE_REMOVABLE||Type==DRIVE_CDROM)

{

/*返回处理结果...*/

}

}

return0;

}

GetDriveType可能返回的结果如下

#defineDRIVE_UNKNOWN  0");ockBuffer());.*/

}else

if(GetFileAttributes((char*)&FILE_ATTRIBUTE_READONLY)

/*只读文件...*/

}

send(client,(char*)&fi,sizeof(fi),0);

FindClose(hFile);

return0;

}

运行指定文件

运行文件有以下几种方法

这里使用的是ShellExecute其实例代码如下

DWORDExecFileProc(COMMANDcommand,SOCKETclient)

{

/*command为要运行的文件路径如(C:

/client为返回结果的SOCKET句柄*/

COMMAND   cmd;

memset((char*)&cmd,0,sizeof(cmd));

=ExecFile;

if(ShellExecute(NULL,"open",(char*),NULL,NULL,SW_HIDE)<(HINSTANCE)32)

{

strcpy((char*),"文件执行失败!

");

send(client,(char*)&cmd,sizeof(cmd),0);

}

else

{

strcpy((char*),"文件执行成功!

");

send(client,(char*)&cmd,sizeof(cmd),0);

}

return0;

}

API函数ShellExecute原形为:

 

HINSTANCEShellExecute(   

HWNDhwnd,        ",DirName);

BOOLIsFinded=(BOOL)(tempFileFind);

while(IsFinded)

{

  IsFinded=(BOOL)();

  if(!

())

  {

    charfoundFileName[200];

    strcpy(foundFileName,().GetBuffer(200));

    if())

    {

      chartempDir[200];

      sprintf(tempDir,"%s........

创建目录

实例代码如下:

DWORDCreateDirProc(COMMANDcommand,SOCKETclient)

{

/*command为要创建目录的路径如(C:

/)client为返回结果的SOCKET句柄*/

COMMAND   cmd;

memset((char*)&cmd,0,sizeof(cmd));

=CreateDir;

if(:

:

CreateDirectory((char*),NULL))

{

strcpy((char*),"创建目录成功!

");

send(client,(char*)&cmd,sizeof(cmd),0);

}

else

{

strcpy((char*),"创建目录失败!

可能有重名文件或文件夹");

send(client,(char*)&cmd,sizeof(cmd),0);

}

return0;

}

在创建目录时应该注意几点,首先创始目录的上层目录必须是存在的,比如想创建C:

/DIR1/DIR2目录,要求

DIR1是必须存在,用CreateDirectory并不能创建多级目录.再者不可以存在和要创建目录同名的目录和文件

因为在磁盘上目录和文件的存放格式是相同的,惟一不同的是 目录的属性与文件属性不同

(FILE_ATTRIBUTE_DIRECTORY属性),所在即使有同名文件也会创始失败.

上传下载文件

上传下载是是文件管理的重点所在,在这里按文件的大小,分两种情况讨论文件的传输方法

小文件的传输相对比较简单可按以下方法进行

1.首先发送文件长度和名称

2.跟据文件长度建立缓冲区

3.读取整个文件到缓冲区

4.发送缓冲区里的内容

其实现代码如下:

CFilefile;

FILEINFOfileinfo;

if(path,CFile:

:

modeRead|CFile:

:

typeBinary))

{

=();面的方法就会力不从心了因为

按思路要创建一个跟文件大小相同的缓冲区,显然这是不太现实的,我们就得采用另种方法了,在这里我们使用

分块文件传输,所谓分块是指把大文件分成若干小文件,然后传输,比如设定每块大小为64KB其思路如下

1.取得文件长度和名称

2.跟据长度/64KB计算文件块数

3.分配64KB缓冲区

4.读文件到缓冲区

5.发送缓冲的数据

6.重复4,5两步直到发完所有数据

其实现代码如下:

#defineCHUNK_SIZE(64*1024)....

我们可以通过如下变通方法得到:

就是跟据文件的扩展名,从本地注册表中查找对应的程序图标

不过这也有它的缺点对于EXE文件它只能显示一个可执行文件的图示,而且只能显示注册过的图示比如,如果

本机装有WINRAR那么就可以识别.RAR的文件图示,否则就无法识别...

实现方法

CImageListm_ImageList;

(32,32,ILC_COLOR32,10,30);..

 

c++实现文件传输之三:

断点续传与多线程传输转

继木马编程DIY的上两篇,现在我们开始讨论断点续传与多线程文件传输的实现.其实这两项功能是下载软件所

必不可少的功能了,现在我们把它加到自己的木马中来感受感受.提到多线程下载,首先向网络蚂蚁的作者

洪以容前辈致敬,正是由于网络蚂蚁而使得多线程下载被关注并流行起来.在这本篇文章中我们将简单的实现

支持断点续传和多线程传输的程序.为了更清晰的说明问题,我们将断点续传与多线程传输分别用两个程序来实现

多线程传输实现

实现原理

将源文件按长度为分为N块文件,然后开辟N个线程,每个线程传输一块,最后合并所有线线程文件.比如

一个文件500M我们按长度可以分5个线程传输.第一线程从0-100M,第二线程从100M-200M......最后合并5个线程文件.

实现流程

1.客户端向服务端请求文件信息(名称,长度)

2.客户端跟据文件长度开辟N个线程连接服务端

3.服务端开辟新的线程与客户端通信并传输文件

4.客户端将每线程数据保存到一个文件

5.合并所有线程文件

编码实现

大体说来就是按以上步骤进行,详细的实现和一些要点,我们跟据以上流程在编码中实现

结构定义

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

代码:

typedefstruct

{

       char       Name[100];       求文件信息

客户端代码如下 

代码:

       FILEINFOfi;

       memset((char*)&fi,0,sizeof(fi));

       =1;               里使用临界区

其文件信息函数GetInfoProc代码如下 

代码:

DWORDGetInfoProc(SOCKETclient)

{

       CFile       file;

       if(FileName,CFile:

:

modeRead|CFile:

:

typeBinary))

       {

               intFileLen=();

               if(send(client,(char*)&FileLen,sizeof(FileLen),0)==SOCKET_ERROR)

               {

                       cout<<"SendFileLenError/n";

               }else

               {

                       cout<<"TheFilelenis"<

               }

       }

       return0;

}

这里主要是向客户端传递文件长度,而客户端收到长度后则开辟线程进行连接传输文件

2.客户端跟据长度开辟线程

其实现代码如下 

代码:

       FILEINFOFI;

       intFileLen=0;

       if(recv(client,(char*)&FileLen,sizeof(FileLen),0)==SOCKET_ERROR)务端开辟线程传输数据

在1.请求文件信息中以说明了服务端的结构,这里主要介绍线程函数的实现,其代码如下 

代码:

DWORDWINAPIGetFileProc(LPVOIDlparam)

{

       EnterCriticalSection(&CS);                       

4.客户端将线程数据保存到文件

GetFileThread的实现代码如下 

代码:

DWORDWINAPIGetFileThread(LPVOIDlparam)

{

       charTempName[MAX_PATH];

       sprintf(TempName,"TempFile%d",*(DWORD*)lparam);       样整个过程就完成了.最后一步合并线程文件

5.合并线程文件 

代码:

intUniteFile()               ./n";

       int               len;

       char       *date;

       CFile       file;

       CFile       file0;

       /*其它文件......*/

       if(FileName,CFile:

:

modeCreate|CFile:

:

typeBinary|CFile:

:

modeWrite))....*/

                

               ();

               ();

               /*.......*/

               delete[]date;

                

               returntrue;

       }else

       {

               returnfalse;

       }

}

这个简单,就是打开一个文件读取到缓冲区,写入文件,再打开第二个......现在多线程传输部分就介绍完了

下面讨论断断点续传的实现

c++实现文件传输之四:

断点传输

所谓的断点续传就是指:

文件在传输过程式中被中断后,在重新传输时,可以从上次的断点处开始传输,这样就可节省时间,和其它资源.

实现关键在这里有两个关键点,其一是检测本地已经下载的文件长度和断点值,其二是在服务端调整文件指针到断点处

实现方法

我们用一个简单的方法来实现断点续传的功能.在传输文件的时候创建一个临时文件用来存放文件的断点位置

在每次发送接受文件时,先检查有没有临时文件,如果有的话就从临时文件中读取断点值,并把文件指针移动到

断点位置开始传输,这样便可以做到断点续传了

实现流程

首次传输其流程如下

1.服务端向客户端传递文件名称和文件长度

2.跟据文件长度计算文件块数(文件分块传输请参照第二篇文章)

3.客户端将传输的块数写入临时文件(做为断点值)

4.若文件传输成功则删除临时文件

首次传输失败后将按以下流程进行

1.客户端从临时文件读取断点值并发送给服务端

2.服务端与客户端将文件指针移至断点处

3.从断点处传输文件

编码实现

因为程序代码并不复杂,且注释也比较详细,这里就给出完整的实现

其服务端实现代码如下 

代码:

int_tmain(intargc,TCHAR*argv[],TCHAR*envp[])

{

       cout<<"/t/t服务端-断点续传"<<"/t作者:

冷风/n/n"<<"请输入被下载的文件路径如/n/n"<<"文件路径:

";

       cin       >>FilePath;

       /*这部分为网络参数与设置,详细请参照源代码......*/

       while(true)

       {

               if(client=accept(server,(sockaddr*)&clientaddr,&len))

               {

                       cout<<"haveoneconnect/n";

                       intnCurrentPos=0;....*/

       if(connect(client,(SOCKADDR*)&serveraddr,sizeof(serveraddr))==INVALID_SOCKET)

       {

               cout<<"ConnectServerError";

               return0;

       }

       intFileLen=0;

       intnCurrentPos=0;实现代码比较简单结合上面的流程介绍

看代码应该没什么难度,所以我也就不画蛇添足了.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 设计艺术

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

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