设计总览
目录
设计总览
编译环境
服务端
客户端
数据包设计
功能设计
IOPC
设计流程
服务端实现(一)
创建服务端项目-Windows桌面向导
CServerSocket()
InitSockEnv()
~CServerSocket()
operator =
InitSocket()
AcceptClient()
DealCommand();
Send()
getInStance()特例设计
MakeDriverInfo()
MakeDirectoryInof()
RunFile()
DownloadFile()
MouseEvent()
MouseEvent结构体
SendScreen()
LockMachine()
UnLockMachine()
DeleteLocalFile()
编译环境
- 编译工具:vs2019
- 编译语言:C/C++
- 操作系统:Windows10
- 辅助工具:git,StarUML
- 网络协议:TCP/IP
- 初步设计模式:客户端-服务端(C/S)模式
- 后期设计模式:一对多模式、客户端mvc架构
服务端
- 初始化网络环境 WSAStartup()
- 创建服务端套接字 socket()
- 初始化服务端信息 sockaddr_in 结构体
- 绑定套接字 bind()
- 监听listen()
- 连接accept()
- 收发数据 recv send()
- 数据处理
客户端
- 初始化网络环境
- 创建客户端套接字socket()
- 初始化客户端网络信息 sockaddr_in结构体
- 连接服务端 connect()
- 接收发数据 recv() send()
- 数据处理
数据包设计
- 包头
- 命令
- 数据长度
- 数据
- 和校验
功能设计
- 驱动盘符遍历
- 文件遍历
- 文件删除
- 文件下载
- 图传操作
- 鼠标操作
- 锁屏
- 解锁屏
IOPC
完成端口CreateIoCompletionPort
重叠结构OVERLAPPED
异步连接AccepEx
异步接收WSARecv
异步发送WSASend
设计流程
服务端实现(一)
创建服务端项目-Windows桌面向导
说明:服务端初步设计,使用Windows桌面向导应用应用程序,在设置属性框里调成窗口隐藏模式
初步设计完成了网络模块初始化、连接客户端、接收发数据功能
步骤:
- 服务端项目创建
- 属性配置,并且忽略4996错误
- CServerSocket类
说明:该类主要用于网络层通信,连接客户端、接收发数据
CServerSocket()
函数原型:CServerSocket();
函数说明:构造函数 用于初始化网络环境,并创建服务器socket
InitSockEnv()
函数原型:BOOL InitSockEnv();
函数说明:初始化网络环境,采用1.1版本网络库
返回值:初始化成功返回TRUE,失败返回FALSE
主要使用的系统函数:WSAStartup()
~CServerSocket()
函数原型:~CServerSocket();
函数说明:析构函数 用于清除网络环境
主要使用的系统函数:WSACleanup()
operator =
函数原型:CClientSocket& operator =(const CClientSocket&);
函数说明:重载复制构造函数,重载操作符号=,用于安全操作,防止错误使用“=”号造成严重后果。
InitSocket()
函数原型:bool initSocket();
函数说明:初始化服务端信息,使用TCP/IP协议族,开启广播域模式(0.0.0.0),监听端口为9527,并绑定到服务端socket,开启监听。
返回值:布尔,成功返回true,失败返回fasle
主要使用的系统函数:
AcceptClient()
函数原型:bool AcceptClient();
函数说明:连接客户端,连接客户端后得到该客户端socket。
返回值:布尔,成功返回true,失败返回fasle。
主要使用的系统函数:
函数原型:SOCKET accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
函数说明:
//参数1:套接字描述符,该套接口在listen()后监听连接
//参数2:由套接口创建时所产生的地址族确定。
//参数3:指向存有addr地址长度的整型数
DealCommand();
函数原型:int DealCommand();
函数说明:接受发数据,解包,取得包里的命令并返回。
返回值: 成功得到命令 , 失败得到 -1。
主要使用的系统函数:
-
- recv()
函数原型:int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags);
函数说明:接收数据
//参数1:使用接收端的套接字
//参数2:缓冲区,用于接收数据
//参数3:指明缓冲区的长度
//参数4:标志功能,一般为0
//返回值:若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,使用WSAGetLastError()得到错误详细信息。
Send()
函数原型:bool Send(const char* pData, int nSize);
函数说明:发送数据
//参数1:需要发送的数据
//参数2:数据大小
//返回值:成功发送返回true,发送失败返回fasle
使用的系统函数:
- send()
函数原型:int send(SOCKET s, const char FAR* buf, int len, int flags);
函数说明:发送数据
//参数1:指定发送端套接字描述符
//参数2:指明需要发送的数据缓冲区
//参数3:该缓冲区的大小
//参数4:标志,一般填0
//返回值:若无错误发生,send()返回所发送数据的总数,否则,返回SOCKET_ERROR错误,使用WSAGetLastError()得到错误详细信息。
getInStance()特例设计
为了防止多次外部多次创建服务器CServerSocket对象从而初始化多次网络环境造成不可预计的后果,采用安全的编程方法
- 将CServerSocket() 构造函数设置为私有成员函数,此时外部无法构造改类
- 在类的私有内创建一个CHelper类用于初始化唯一的CServerSocket对象,而外部无法访问CHelper类
- 声明一个CHelper类对象为静态私有成员,并且在cpp中实例化,从而当程序加载初始化时,首先初始化CHelper类,此时调用getInstance()即可初始化CServerSocket对象
- 对外只放出一个静态函数接口 getInstance(),无法重复创建CServerSocket对象
- 外部只能通过getInstance()得到唯一一个服务端socket。
- CPacket数据包类
- 数据包设计
- 构造函数,初始化
- 函数原型:CPacket(WORD nCmd, const BYTE* pData, size_t nSize);
函数说明:数据包封包构造函数,用于把数据封装成数据包
//参数1:命令
//参数2:数据指针
//参数3:数据大小
- 函数原型:CPacket(const BYTE* pData, size_t& nSize);
函数说明:数据包解包,将包中的数据分配到成员变量中
//参数1:数据指针
//参数2:数据大小
- 数据包类总览
- 功能函数设计
MakeDriverInfo()
函数原型:int MakeDriverInfo();
函数说明:查看本地磁盘分区,并把信息打包成数据包
//返回值 int 成功返回0,失败返回 -1
使用主要系统函数:int __cdecl _chdrive(int _Drive) //通过切换26个字母盘符是否能切换成功来判断盘符存在
MakeDirectoryInof()
函数原型:int MakeDriverInfo();
函数说明:遍历磁盘文件,并将得到的信息打包成数据包。
//返回值:成功返回0,路径错误返回-1,没有权限返回-2,空文件返回-3。
内部使用主要函数
- int __cdecl _chdir(const char* _Path)
//函数说明:通过切换到输入的路径来判断是否存在该路径
//参数1:路径
- int __cdecl _findfirst(const char* _FileName, struct _finddata_t* _FindData)
//函数说明:获得当前文件节点
//参数1:文件路径 填 “*” 表示匹配所有文件, “D:\\*.txt” 表示D盘下所有.txt文件
//参数2:文件信息的结构体 out型
//返回值:文件节点
- int __cdecl _findnext(int _FindHandle, struct _finddata_t* _FindData)
//函数说明:获得文件节点的下一个文件节点
//参数1: 当前文件节点
//参数2: 下一个文件的信息结构体 out型
//返回值: 下一个文件节点
通过以上两个函数配合,从盘符开始,通过do...while() 循环可得到遍历文件
RunFile()
函数原型:int RunFile();
函数功能:运行本地文件,通过数据包中的路径,执行文件
内部使用主要系统函数:
HINSTANCE ShellExecute(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
//函数说明:运行指定文件
//参数1:窗口句柄 这里填NULL,表示不指定父窗口
//参数2:用于指定进行的操作,当为NULL时,表示默认打开
//参数3:可执行文件完整路径
//参数4:可执行文件的命令行,这里设置为NULL
//参数5:指定默认目录
//参数6:初始化显示方式,模拟正常打开文件使用 SW_SHOWNORMAL
返回值:执行成功会返回应用程序句柄
DownloadFile()
函数原型:int DownloadFile()
函数说明:下载文件,获取数据包中的路径,使用文件操作函数读取文件到缓冲区,并打包发送回客户端。
内部使用的主要系统函数:
- errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );
//函数说明:以某种方式打开指定文件
//参数1:文件指针out型,
//参数2:文件路径
//参数3:打开方式,这里以二进制读的方式打开,为 ”rb”
//返回值:成功返回0,失败返回错误码
- int fseek(FILE *stream, long offset, int fromwhere);
//函数说明:设置文件指针stream的位置
//参数1:文件指针
//参数2:偏移,这里填空或者0
//参数3:将文件指针指向某个位置,SEEK_SET表示指向文件头,SEEK_END表示指向文件尾
//返回值: 成功返回0,失败返回非0值,并设置error的值,可以用perror()函数输出错误。
- size_t fread(void* buffer,size_t size,size_t count,FILE* stream);
//函数说明:将文件指针指向的数据以数据流的方式读取到目标缓冲区
//参数1:指定的缓冲区
//参数2:一次读取的宽度
//参数3,读取的次数
//参数4:文件流
//返回值:返回成功读取的对象个数,若出现错误或到达文件末尾,则可能小于count。
MouseEvent()
函数原型:int MouseEvent();
函数说明:处理鼠标操作
//成功返回0,失败返回-1
内部使用的系统函数:
- BOOL SetCursorPos(int X,int Y);
//函数说明:设置鼠标坐标
//参数1:鼠标x坐标
//参数2:鼠标y坐标
//返回值:如果成功,返回非零值;如果失败,返回值是零,可调用GetLastError()得到详细信息
- WIN系统 mouse_event(DWORD dwFlags,DWORD dx,DWORD,dy,DWORD dwData,ULONG_PTR dwExtraInfo);
//函数说明:鼠标响应事件
//参数1:鼠标动作,如点击、双击、左键、右键等
//参数2:鼠标x坐标
//参数3:鼠标y坐标
//参数4:鼠标轮滑,正数向前滑,负数向后滑,当dwFlags为轮滑操作时候才设置,一般为0
//参数5,指定与鼠标事件相关的值,调用GetMessageExtraInfo()来得到
//返回值:
MouseEvent结构体
说明:设计一个鼠标信息的数据结构,用于接收客户端鼠标操作命令
nButton:0表示左键,1表示右键,2表示中键,4没有按键
nAction: 0表示单击,1表示双击,2表示按下,3表示放开,4不作处理
SendScreen()
函数原型:int SendScreen();
函数说明:远程桌面,采用图传功能实现
内部使用的函数:
- HDC GetDC(HWND hWnd);
//功能作用:检索指定窗口的客户区的显示上下文环境句柄
//参数1:指定窗口句柄
//返回值:返回值表示指定窗口区域的DC句柄,失败返回NULL
- int GetDeviceCaps(HDC hdc,LPRECT lprect);
//函数功能:获取DC的指定数据
//参数1:指定的HDC句柄
//参数2:指定定数据。BITSPIXEL:像素相连颜色位数, HORZRES:宽, VERTRES:高
//返回值:int数据
LockMachine()
函数原型:int LockMachine();
函数说明:锁机,通过创建线程,让线程创建大于整个屏幕的对话框,阻挡鼠标点击操作,并将鼠标固定在一个位置,另外做一个消息循环,用于恢复锁机。暂时未实现锁定键盘操作。
内部使用的函数操作:
锁定鼠标功能实现:
- ShowCursor(BOOL bShow); //光标操作
- ::ShowWindow(HWND hWnd, int nCmdShow); //隐藏或显示窗口
- ClipCursor(RECT *lpRect); //设置鼠标坐标
- BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
//函数说明:从消息队列中取数据,本次功能中此处用于解锁。
//参数1:消息结构体指针,用于存放取得的数据
//参数2:取得消息的窗口句柄
//参数3:指定被检索的最小消息值的整数,一般用于消息过滤,为0时,无过滤
//参数4:指定被检索的最大消息值的整数,一般用于消息过滤,为0时,无过滤
//返回值
UnLockMachine()
函数原型:int UnLockMachine();
函数功能:解锁,向锁机线程发送post消息
内部使用的系统函数:
- BOOL PostThreadMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam)
//功能作用:将消息发送到指定线程的消息队列里
//参数1:指定的线程id
//参数2:指定的消息类型
//参数3:消息w,一般是一些常量值
//参数4:消息l,一般是传指针
//返回值:如果函数调用成功,返回非零值。如果函数调用失败,返回值是零。
DeleteLocalFile()
函数原型:int DeleteLocalFile();
函数功能:删除指定文件
//返回值:成功返回0,失败返回非0值
内部使用的函数:
- BOOL DeleteFile(LPCWSTR lpFileName)
//功能作用:删除指定文件,测试删除为永久删除,不放入回收站,需要调用者的权限足够
//参数1:指定文件路径的指针
//返回值:成功返回0,失败返回非0值