Skip to content

2.概要&详细设计

ligaojin edited this page May 12, 2019 · 8 revisions

系统详细设计

设计概要:

  • 使用Linux system call hook技术进行open、close等函数的劫持
  • hook劫持之后添加自定义的操作来达到项目需求
  • 通过HOOK向客户端发送文件信息且客户端与服务器建立联系

详细设计:

客户端结构设计和子模块划分

  1. 与hook建立联系,并且传递消息
  2. 向服务器发送文件的相关信息
  3. 根据服务器反馈的消息控制hook中的操作(如果无法连接到服务器则中断“所有”操作)

服务端结构设计和子模块划分

结构设计

  • Server采用Reactor模式:
    • 实现为epoll+线程池
  • 工作线程操作流程:
    • 备份:
    1. 接收客户端的消息
    2. 备份其中传递进来的标记、MAC地址、文件名、文件内容
    • 恢复:
    1. 接受客户端的消息
    2. 根据传递进来的标记、MAC地址、文件名、文件内容向客户端发送文件

数据格式设计

配置文件格式

通信协议格式

typedef struct tag    //消息包
    {
        int sign = 0;   //标记位
        char mac_addr[MAC_ADD_SIZE];   //MAC地址
        char file_name[FILE_NAME_LEN];    //文件名
        char data[BUFF_SIZE];     //文件内容
    }TAG;

代码结构设计

客户端

HOOK部分 形参 作用
Get_file_size char* path 获取文件的大小
writen 和write的形参相同 自己封装的write防止有一部分内容没有发送
readn 和read的形参相同 自己封装的read防止一部分内容没有读完
Set_memory char * path 读取文件内容设置共享内存
Send_link Char * pathname 发送文件的绝对路径
open 和本来的open一样 Hook的open
close 和本来的close一样 HOOK的close
client 形参 作用
Ip.getlocalInfo 获取当前使用的网卡和mac地址
addfd Epollfd,fd,enable_et 添加到epoll监听队列之中
Rm_fd Epollfd,fd 从epoll队列中删除
writen 和write的形参相同 自己封装的write防止有一部分内容没有发送
Get_shm Int sockfd 获取共享内存内容
Send_img Int sockfd 获取消息队列内容
printdir Char * dir int depth,int fd 遍历监控目录,把子目录放入队列之中
Handle_events Int epollfd,int fd int sockfd Inotify触发事件调用队列
Get_file Int sockfd Hook发送客户端close请求之后,在服务器上请求文件

服务器

  • Monitor类的设计
class monitor
{
public:
    static const int BUFF_SIZE = 1024;
    static const int MAC_ADD_SIZE = 18;
    static const int FILE_NAME_LEN = 200;
    static const int BACKUP_F_NAME = 300;
public:
    monitor() {}
    ~monitor() {}

private:
    typedef struct tag    //消息包
    {
        int sign = 0;   //标记位
        char mac_addr[MAC_ADD_SIZE];   //MAC地址
        char file_name[FILE_NAME_LEN];    //文件名
        char data[BUFF_SIZE];     //文件内容
    }TAG;

public:
//All socket上的event都被注册到同一个epoll内核时间表中
//所以将epoll文件描述符设置为静态的
    static int m_epollfd;
//初始化新的接受链接
    void init(int sockfd,const sockaddr_in& addr);
    void close_mon(bool real_close = true );
//处理请求 入口
    void process();
//收消息
    bool recv_masg();
//发消息
    bool send_masg();
private:
//备份文件名称
    char backup_f_name[BACKUP_F_NAME];
    void init();//内部init
    TAG* masg = new TAG;  //消息体
    void backup();
    void recover();
private:
//该请求链接的socket和对方的socket地址
    int m_sockfd;
    sockaddr_in m_address;
    int fd; //文件描述符

};