关于利用Tcp库来实现文件传输

文件传输主要是学习文件处理的windows API函数、数据结构操作和 string操作。

首先应用库来建立一个服务器和一个客户端,都是单线程。

服务器说明:建立一个结构体tTransFile

struct tTransFile
{
    int nLen;
    int nIdx;
    char szFileName[255];
    UINT32 uFileSize;
    char* GetData()
    { 
       return  (char*) (this + 1);
    }
}

我建立的是一个比较简单的文件传输,要传入一个存储该文件的路径,然后分析这个路径,需要应用API函数FindFirstFile

HANDLE FindFirstFile(
 LPCTSTR lpFileName, //文件或文件夹路经r
 LPWIN32_FIND_DATA lpFindFileData 
);
BOOL FindNextFile(
 HANDLE hFindFile,
 LPWIN32_FIND_DATA lpFindFileData 
);
BOOL FindClose(HANDLE hFindFile );

 

typedef struct _WIN32_FIND_DATA {
 DWORD dwFileAttributes; //文件属性
 FILETIME ftCreationTime; // 文件创建时间
 FILETIME ftLastAccessTime; // 文件最后一次访问时间
 FILETIME ftLastWriteTime; // 文件最后一次修改时间
 DWORD nFileSizeHigh; // 文件长度高32位
 DWORD nFileSizeLow; // 文件长度低32位
 DWORD dwReserved0; // 系统保留
 DWORD dwReserved1; // 系统保留
 TCHAR cFileName[ MAX_PATH ]; // 长文件名
 TCHAR cAlternateFileName[ 14 ]; // 8.3格式文件名
} WIN32_FIND_DATA, *PWIN32_FIND_DATA;

  
  
lpFileNameString,欲搜索的文件名。参数可如下:
c:\Windows\*.* //在c:\Windows目录中查找所有文件 
c:\Windows\System32\*.dll //在c:\Windows\System32目录中查找所有dll文件 
c:\Windows\System.ini ;在c:\Windows目录中查找System.ini文件 
c:\Windows\a???.* // 在c:\Windows目录中查找所有以a开头的文件名长度.为4个字符的文件 
Test.dat //在当前目录查找Test.dat文件
 *.* //在当前目录查找所有文件



也可以使用下面这个方法获取文件信息:

BOOL GetFileInformationByHandle(
HANDLE hFile, // 文件的句柄 
LPBY_HANDLE_FILE_INFORMATION lpFileInformation 
);


 

typedef struct _BY_HANDLE_FILE_INFORMATION { 
 DWORD dwFileAttributes; 
 FILETIME ftCreationTime; 
 FILETIME ftLastAccessTime; 
 FILETIME ftLastWriteTime; 
 DWORD dwVolumeSerialNumber; // 文件所在的磁盘的序列号
 DWORD nFileSizeHigh; 
 DWORD nFileSizeLow; 
 DWORD nNumberOfLinks; //链接的数目
 DWORD nFileIndexHigh; 
 DWORD nFileIndexLow; 
} BY_HANDLE_FILE_INFORMATION;

我主要应用的是FindFirstFile,WIN32_Find_DATA 应用里面的cFileName,然后获得HANDLE后就可以接着查询应用FINDNXETFILE,里面应用的结构体相同,也就是同样我们要取的都是文件的name,当然第一次和第二次取出来的都是”。“,”。。“,这是文件的两级目录,然后才能取到第一个文件的名称,然后一直循环取FINDNEXTFILE,当然是成功的情况下,如果失败返回INVALID_HANDLE_VALID。我在File_Server类中,还建立一个list<string>安放取到的文件名称。

为处理list<string>我还建立一个iterator it,用他来取用队列中的string字符串。下面就应该是接到信息然后分析这个信息操作。

这个信息就是协议,也是结构体。我收到的可能不是协议类型,如此我们强制转换该数据,因为这就是一个下载服务器(当然我是这么认为的,内网中可用),主要监听的就是要下载第几个文件,知道nIdx后,就可以操作知道it的指向队列中第几个字符串,然后通过FindAndOpenFile函数(这个是我自己起的名不是API),FindAndOpenFile主要是字符串操作把该文件的路径拼完全,然后用此路径调用API函数CreateFile获取文件句柄hFile,用hFile先调用GetFileSize,获取文件的大小,然后再掉SetFilePointor,确定文件每次开始读取都从文件开始处开始。

回信息操作:1、获取文件大小赋值给结构体中uFileSize

                        2、获取文件名称复制给szFileName

                        3、分析读取信息ReadFile中GetLeng,把第一读取的大小记录下来。

                        4、填充整个数据的大小nLen,他的大小包括第一次读取到的文件的大小+结构体的大小。

                        5、这个最重要差点忘了,就是可能数据比较到,只应用结构体操作可能他的存放空间不够,也就是在栈上操作空间不够,如此我们需要在堆上操作这个要发送出去的数据。new char[MAX_SIZE_SEND],然后应用强制转换等等操作,就可以把这个数据发出去,(重点是send中数据的长度,不可以用sizeof+指针,要用nLen的长度).

                       6、后面的操作就是在文件大小和读取大小之和比较的条件下,开始不断的循环发生数据。直到完成发送,完成后,记得把it还原。关闭HANDLE,回收堆内存。

                       7、忘啦一条,就是关闭HANDLE,应用完FindNextFile后要关闭HANDLE。

客户端操作:

这个比较简单,1、获取文件存储的地址

                            2、建立和服务器连接的条件端口和IP

                            3、建立连接后,发送信息,就是结构体,也是协议,主要填写的是nIdx,就是要下那个文件。发送这个数据操作和服务器中5相同的操作。发送完后要回收堆内存。                           

                            4、接收信息,首先要分析这个数据,分析协议,取出文件大小、文件名称、还有数据和结构体分离。

                            5、根据结构中的文件名称和1的操作通过字符串操作CreateFile,并且记录下第一次收到的数据的大小。

                            6、开始应用WriteFile写入文件,两方面来保证收到的数据完成,一是recv,二是收到的数据和文件大小比较,如果相等就写入完成。

                            7、处理关闭不需要的HANDLE,SOCKET和各种堆内存。

                           


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值