首页 / 软件开发 / C++ / 基于select I/O模型的远程目录浏览与多线程文件下载
基于select I/O模型的远程目录浏览与多线程文件下载2010-11-02李建成摘要:服务器端基于select I/O模型。为防止程序界面阻塞, 有一个子线程用于不断接收socket并select其中的处理。客户端只有一个线程函数, 不过其利用率很高, 可用于远程目录交换, 请求文件大小, 创建若干线程来下载文件。文件传输有上传和下载,还有对等传输, 这个项目中, 传输文件具体指下载。正文:一 数据及1 传送包, 客户端主线程给子线程传递的结构体typedef struct{
char packetType; // 请求类型 r:request rootdriver d:directory f:file D::data
unsigned int length; //用于传送int类型
char content[2000]; //传送的内容
}DATA_PACKET;
请求类型:"r":服务器逻辑盘符, d; 盘符和文件夹下的文件夹和文件名, f":文件大小, D:文件内容。在客户端请求下载文件, length末两位用于记录下载的线程总数, 前面的用于记录当前的线程序号。在服务器端这个反运算很容易实现。在请求文件大小和请求下载时, content都用于保存请求文件的绝对路径.这个在服务器端做反运算要用自定义函数处理。2 全局变量(用于线程间的通信)char* pDrives; // 数据缓冲
CString arrFiles[200]; //文件目录字符串数组
CString savePath; //文件保存路径
long fSize=0l, ,recvFSize=0l; //文件大小,已经接收的文件大小
CString strIP; //IP
bool thrFlag=false; //下载线程创建置位
理论上讲, 在程序中应尽量避免使用全局变量,因为破坏程序结构, 君不见Java和C#完全面向类。但为了方便, 所以就用了全局变量, 且是应用程序级的, 这样线程间的通讯很方便。值得一提的是, 这里thrFlag很重要, 它涉及到确保线程创建一定正确的问题, 在后面“要注意的几点问题”中会更详细的讨论。3 目录树类CExtnTreeCtrl::CTreeCtrl该类继承于CTreeCtrl类, 主要扩展获得树的某个项目在整棵树的完整路径, 以便把这个路径规格化后能向服务器请求文件。在这里还实现了将一个完整路径转为文件名的函数。对于如何构造这棵树, 有一个很方便高效的办法:双击树,把双击的项作为根.如果为盘符或文件夹, 就发送请求给服务器, 待服务器返回, 自动填充在这个项下。如果为文件, 则该项名有扩展名, 将请求下载。这个办法操作起来方便, 而且还提高了系统性能, 至少在局域网是这样。如果就一次从服务器中请求整个文件系统的目录内容, 肯定会慢很多。4.参数设置对话框类 CSetParam这个类用于设置下载的线程数目, 和默认的保存文件夹路径。这个类会写一个“Setting.ini”文件在C盘以保存参数。具体来说,如果用户一直都没有设置这些参数的话, 那么GetPrivateProfileString(...)试图读取"C:Setting.ini"文件会返回默认的线程数0, 和一个不是表示路径的字条串“defaultpath”, 这时, 下载程序会自动设置参数, 分别为3, “C:”。二 几个要注意的问题1 MFC与Windows API就多线程编写网络程序而言, 如果使用MFC的CAsyncSocket或CSocket, 主线程给子线程传参量是一个非常头痛的问题, 如果用Windows API实现就灵活多了。在文件操作方面, CFile还不错。尽管如此, 我还是用了Windows API函数, 为了设计满足要求。