《远程控制》-服务端实现(一)

设计总览

目录

设计总览

编译环境

服务端

客户端

数据包设计

功能设计

IOPC

设计流程

服务端实现(一)

创建服务端项目-Windows桌面向导

CServerSocket()

InitSockEnv()

~CServerSocket()

operator =

InitSocket()

AcceptClient()

DealCommand();

Send()

getInStance()特例设计

MakeDriverInfo()

MakeDirectoryInof()

RunFile()

DownloadFile()

MouseEvent()

MouseEvent结构体

SendScreen()

LockMachine()

UnLockMachine()

DeleteLocalFile()

编译环境

  1. 编译工具:vs2019
  2. 编译语言:C/C++
  3. 操作系统:Windows10
  4. 辅助工具:git,StarUML
  5. 网络协议:TCP/IP
  6. 初步设计模式:客户端-服务端(C/S)模式
  7. 后期设计模式:一对多模式、客户端mvc架构

服务端

  1. 初始化网络环境 WSAStartup()
  2. 创建服务端套接字 socket()
  3. 初始化服务端信息 sockaddr_in 结构体
  4. 绑定套接字 bind()
  5. 监听listen()
  6. 连接accept()
  7. 收发数据 recv send()
  8. 数据处理

客户端

  1. 初始化网络环境
  2. 创建客户端套接字socket()
  3. 初始化客户端网络信息 sockaddr_in结构体
  4. 连接服务端 connect()
  5. 接收发数据 recv()  send()
  6. 数据处理

数据包设计

  1. 包头
  2. 命令
  3. 数据长度
  4. 数据
  5. 和校验

功能设计

  1. 驱动盘符遍历
  2. 文件遍历
  3. 文件删除
  4. 文件下载
  5. 图传操作
  6. 鼠标操作
  7. 锁屏
  8. 解锁屏

 

IOPC

完成端口CreateIoCompletionPort

重叠结构OVERLAPPED

异步连接AccepEx

异步接收WSARecv

异步发送WSASend

 

设计流程

服务端实现(一)

创建服务端项目-Windows桌面向导

说明:服务端初步设计,使用Windows桌面向导应用应用程序,在设置属性框里调成窗口隐藏模式

初步设计完成了网络模块初始化、连接客户端、接收发数据功能

步骤:

  1. 服务端项目创建
    《远程控制》-服务端实现(一)_第1张图片
  2. 属性配置,并且忽略4996错误
    《远程控制》-服务端实现(一)_第2张图片
  1. CServerSocket类

说明:该类主要用于网络层通信,连接客户端、接收发数据

CServerSocket()

函数原型:CServerSocket();

函数说明:构造函数 用于初始化网络环境,并创建服务器socket
《远程控制》-服务端实现(一)_第3张图片

InitSockEnv()

函数原型:BOOL InitSockEnv();

函数说明:初始化网络环境,采用1.1版本网络库

返回值:初始化成功返回TRUE,失败返回FALSE

主要使用的系统函数:WSAStartup()

~CServerSocket()

函数原型:~CServerSocket();

函数说明:析构函数 用于清除网络环境

主要使用的系统函数:WSACleanup()
《远程控制》-服务端实现(一)_第4张图片

operator =

函数原型:CClientSocket& operator =(const CClientSocket&);

函数说明:重载复制构造函数,重载操作符号=,用于安全操作,防止错误使用“=”号造成严重后果。

《远程控制》-服务端实现(一)_第5张图片

InitSocket()

函数原型:bool initSocket();

函数说明:初始化服务端信息,使用TCP/IP协议族,开启广播域模式(0.0.0.0),监听端口为9527,并绑定到服务端socket,开启监听。

返回值:布尔,成功返回true,失败返回fasle

主要使用的系统函数:

    • bind()
    • listen()

《远程控制》-服务端实现(一)_第6张图片

AcceptClient()

函数原型:bool AcceptClient();

函数说明:连接客户端,连接客户端后得到该客户端socket。

返回值:布尔,成功返回true,失败返回fasle。

主要使用的系统函数:

    • accept()

函数原型:SOCKET accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
函数说明:
//参数1:套接字描述符,该套接口在
listen()后监听连接
//参数2:由套接口创建时所产生的地址族确定。
//参数3:指向存有addr地址长度的整型数

《远程控制》-服务端实现(一)_第7张图片

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()得到错误详细信息。

《远程控制》-服务端实现(一)_第8张图片

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()得到错误详细信息。

《远程控制》-服务端实现(一)_第9张图片

getInStance()特例设计

为了防止多次外部多次创建服务器CServerSocket对象从而初始化多次网络环境造成不可预计的后果,采用安全的编程方法

  • 将CServerSocket() 构造函数设置为私有成员函数,此时外部无法构造改类
    《远程控制》-服务端实现(一)_第10张图片
  • 在类的私有内创建一个CHelper类用于初始化唯一的CServerSocket对象,而外部无法访问CHelper类
    《远程控制》-服务端实现(一)_第11张图片
  • 声明一个CHelper类对象为静态私有成员,并且在cpp中实例化,从而当程序加载初始化时,首先初始化CHelper类,此时调用getInstance()即可初始化CServerSocket对象
  • 对外只放出一个静态函数接口 getInstance(),无法重复创建CServerSocket对象
    《远程控制》-服务端实现(一)_第12张图片
  • 外部只能通过getInstance()得到唯一一个服务端socket。

 

  1. CPacket数据包类
  1. 数据包设计
    《远程控制》-服务端实现(一)_第13张图片
  2. 构造函数,初始化
  3. 函数原型:CPacket(WORD nCmd, const BYTE* pData, size_t nSize);
    《远程控制》-服务端实现(一)_第14张图片

函数说明:数据包封包构造函数,用于把数据封装成数据包
//参数1:命令
//参数2:数据指针
//参数3:数据大小

  1. 函数原型:CPacket(const BYTE* pData, size_t& nSize);
    函数说明:数据包解包,将包中的数据分配到成员变量中
    //参数1:数据指针
    //参数2:数据大小

    《远程控制》-服务端实现(一)_第15张图片
  2. 数据包类总览
    《远程控制》-服务端实现(一)_第16张图片

 

  1. 功能函数设计

MakeDriverInfo()

函数原型:int MakeDriverInfo();

函数说明:查看本地磁盘分区,并把信息打包成数据包
//返回值 int 成功返回0,失败返回 -1
使用主要系统函数:int __cdecl _chdrive(int _Drive) //通过切换26个字母盘符是否能切换成功来判断盘符存在

《远程控制》-服务端实现(一)_第17张图片

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结构体

说明:设计一个鼠标信息的数据结构,用于接收客户端鼠标操作命令
《远程控制》-服务端实现(一)_第18张图片
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数据
  • 《远程控制》-服务端实现(一)_第19张图片

LockMachine()

函数原型:int LockMachine();

函数说明:锁机,通过创建线程,让线程创建大于整个屏幕的对话框,阻挡鼠标点击操作,并将鼠标固定在一个位置,另外做一个消息循环,用于恢复锁机。暂时未实现锁定键盘操作。

内部使用的函数操作:
锁定鼠标功能实现:

  • ShowCursor(BOOL bShow);               //光标操作
  • ::ShowWindow(HWND hWnd, int nCmdShow);  //隐藏或显示窗口
  • ClipCursor(RECT *lpRect);              //设置鼠标坐标
    《远程控制》-服务端实现(一)_第20张图片
  • 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值

你可能感兴趣的:(远程控制项目,c++)