远程控制项目(1)
一、C/S架构
1.项目的分析
1 首先,对项目的服务端和客户端,相对来说服务端的架构是较难的部分
2 其次,在今后的联调过程中是需要服务端和客户端来配合的,所以优先写服务器
2.Windows下的服务端
1 首先对服务器的了解
2 在实际中服务器可能是多个的
3 服务器可能有多个的网络接入,比如接入电信、移动
4 然后再由这个服务器连接到其他的服务器,称为内网
5 内网里可能有数据库服务器、逻辑服务器等
6 这样的结构的好处就是当用户接入服务器是对内网的服务器ip是不知道的
7 这样还可以让效率更高,内网可以接更高的带宽
3.第一个类
1 静态变量的初始化在首次被调用的时候才会被初始化 销毁是在程序销毁的时候
2 如果是全局的静态变量会在main函数之前初始化 在main函数返回之后会被析构
3 单例的理解
3.1 单例的存在的意义就是有一个类,这个类可以被随时的创建对象,如果在main函数的开始就声明一个这样的对象,这样就导致了本来使用的函数或者成员被提前析构,为了避免这样的现象而产生了单例
3.2 单例可以从硬件、语法和规范三个方面入手,比如LINUX的随机数的产生就是使用了硬件限定,这是最强的从硬件方面限定随便使用类来声明对象
3.3 静态方法和成员没有this指针,所以可以从这方面入手创建一个单例
3.4 单例就是要把构造函数声明为私有的,其中包括等号重载、复制构造函数、构造函数以及析构函数
3.5 私有的函数以及成员是无法从外部直接调用的,所以要间接的使用
3.6 这里就要用到静态了
3.7
static CServerSocket* getInstance() {
if (m_instance == NULL) {
m_instance = new CServerSocket();
}
return m_instance;
}
3.8 声明一个变量为静态成员变量,并作初始化,要显式的初始化这个变量,还有就是在类里面创建一个cHelper类,这个类里面做的是就是在构造的时候创建单例,析构的时候将静态变量置空以及delete new的对象
CServerSocket* CServerSocket::m_instance = NULL;
CServerSocket::cHelper CServerSocket::m_helper;
CServerSocket* pserver = CServerSocket::getInstance();
3.9 如果没有显式的初始化m_instance,就会出现以下错误
二、后台运行和包设计与实现
1.后台运行
1 现在做的是服务端,所以要让程序运行在后台
2 使用项目属性页对此功能进行设置
2.设计包
1 使用2个字节作为包头
2 4个字节作为长度
3 2个字节作为命令
4 第四部分是包数据所在的地方
5 使用2个字节作为校验
总结:
在这里使用的校验是和校验,和校验一般来说是最简单方便的校验方式
包头的作用是: 1 包头一般设置为一个特定的,包里面有很大的概率不会出现的数据,比如0XFEFF\0XFFFE等这些数据 2 有包头在可以跳过损坏的数据 3 跳过网络上的嗅探包,因为嗅探包的协议是与自己写的东西是不一样的 4 还有就是其他应用的误发的数据也会被跳过
三、磁盘分区信息的获取
磁盘分区的区分:一般来说,磁盘的盘符是由英语的26个字母作为盘符的,比如数字1就代表A盘,2就是B盘,依次类推。
获取磁盘分区使用的函数就是_chdrive(),这个函数的参数为盘符的编号,我是这样理解的:当你的电脑有C盘,也就是3,即是说_chdrive(3)的返回值为0,使用result += ‘A’ + i - 1;这样就可以把磁盘分区的信息存到一个字符串里了
四、获取文件和目录信息
1.首先就是要获取文件或者目录信息,那就要先知道对应文件的路径,怎么获取到呢,这就要用到打包的数据了,这个数据要从包数据里面来获取
2.获取到路径信息以后就要判断路径,_chdir()这个函数就是用来判断路径是否是目录,返回值为0的时候就说明这个路径是目录
3.有文件信息了,但是还要有地方存这些信息,接下来就是要创建一个结构体来存放这些信息,这些信息有:是否是有效的数据、是否是目录、是否还有后续内容或者目录、文件名
4.如果判断的结果为这个路径是目录信息,那么就要对目录下的文件进行查找,也就是对所有的文件进行查找,如果查找不到任何的文件,就说明这是一个空目录,返回错误信息
5.如果这些都不是,那么接下来就是对目录进行下一级的判断了,因为文件的存储结构类似为树,目录就相当于主干,下级目录就相当于树枝,依次向下就是分支、叶结点等
6.每次查找完都要发送一次包,这样可以做到与用户的交互
7.查找完一次都判断是否还有后续,也就是是否还有树枝,叶子等
五、打开文件和下载文件
1.打开文件的操作,不过不是每个文件都是文件,还有一些图片、应用程序、文档等等
1.2还是要得到对应的路径,还是要从包数据里面获取
1.3 使用ShellExecuteA(NULL, NULL, strPath.c_str(), NULL, NULL, SW_SHOWNORMAL);对相应的文件进行操作
1.4这个函数的作用简单来说就是激活对应的工具打开对应的程序、图片、视频等
2.下载文件,其实经过服务端到客户端,传输的还是数据,不是一个文件
2.1 获取文件路径信息
2.2 打开文件,使用读二进制的方式打开文件,因为文本文件可以使用二进制的方式打开,但是二进制文件就不可以使用文本的方式打开
2.3 读到文件,对文件的长度进行读取,fseek()和ftell()函数配合使用会得到文件的长度,当然再做完这个操作以后,还要执行fseek(),SEEK_SET设置为文件开头的位置
2.4 接下来就是对文件的内容进行读取了,每次读1个字节,读1024次,每次读完都要发送一次数据
2.5 操作完成,记得关闭文件