又到了每天写日报的时间了。


文章目录

  • 总结昨日
  • 日报
  • 进度
  • 项目周期调整
  • 解压包模块设计
  • 解压包模块代码(可编译,未测试)
  • 数据库模块修改
  • 今日计划
  • 原计划
  • 实际计划


总结昨日

日报

还是先记录前一天的日报情况。

进度

昨天大家都走出了第一步,客户端陆陆续续都在画界面,服务器方面我也初步建设好数据库和解压包两个模块,其他人也在抓紧学习,呈现出明显的分化,努力的人越努力。

项目周期调整

昨天还做出了一个调整,鉴于大家压力都比较大,所以决定将之后的一个项目日分为两天,天天开会大家会觉得没什么好讲的了。相应的改动便是将项目周期由12个工作日改为10个项目日,实际时间由原先的16天延长为20天。

此外,会议主要讨论了解压包模块应该如何进行,接下来会看到我设计的类图。

解压包模块设计

FTP文件管理项目(本地云)项目日报(四)_.net

解压包模块代码(可编译,未测试)

//packet_base.h

#pragma once
#include<string>

#define MAX_PACKET_LENTH 1024
//设置包最大长度为1024,
// ! ! ! 暂时不考虑会太小的情况 ! ! !

typedef struct packet_header_st
{
int fd;//用于前后端通信即目标客户端fd(服务器用到)
int funcId; // 功能号
//登录包0x01,注册包0x02,找回密码0x03,修改密码0x04

//客户端获取文件列表0x11,上传文件0x12,下载文件0x13,共享文件0x14,除获取列表外各种文件业务应答0x15
//心跳0x21

int optid; // 操作码:请求0x00 和 应答0x01

int usrlenth;// 包体的长度
int packet_seq; //包序号
int packet_sum; //包总数

char srcAddr[6]; //预留
char dstAddr[6]; //预留

int syn; // 判断包头是否正确 0x04
}packet_header_t;

/************接入层数据包尾************/

typedef struct packet_tali_st//包尾,用来验证数据包的完整性
{
int pack_tail;//设置为0x05
}packet_tali_t;

/************数据包报文整体************/

typedef struct packet_all_st
{
packet_header_t Head;
char* body;
packet_tali_st tail;
}packet_all_st;



class PacketBase
{
protected:
int m_Size;
int Body_Size; //包体大小
packet_header_t Head;
packet_tali_t Tail;
char* Body;
char m_Data[MAX_PACKET_LENTH];

public:
PacketBase();
~PacketBase();
bool pack();
bool unpack();
char* getBody();
packet_header_t* getHead();
packet_tali_t* getTail();
char* getData();
int getSize();
void setSize(int size);
void setBodySize(int bodysize);
PacketBase& operator =(const PacketBase& packet);
};
//packet_base.cpp

#include "PacketBase.h"
#include<iostream>

PacketBase::PacketBase() {
memset(&Head, 0, sizeof(Head));
memset(&Tail, 0, sizeof(Tail));
}

PacketBase::~PacketBase() {
delete Body; //如果要用智能指针的话,先测一下大小
}

bool PacketBase::pack()
{
Body = new char[Body_Size];
memcpy(m_Data, &this->Head, sizeof(packet_header_t));
memcpy(m_Data + sizeof(packet_header_t), this->Body, sizeof(Body)); //这个Body长度在封包的时候定
memcpy(m_Data + sizeof(packet_header_t) + sizeof(Body), &this->Tail, sizeof(packet_tali_t));

return true;
}

bool PacketBase::unpack()
{
if (Body_Size <= 0) { //如果数据不足
std::cout << "数据包破损" << std::endl;
return false;
}

Body = new char[Body_Size]; //防止越界可以在这里下手
memcpy(&this->Head, m_Data, sizeof(packet_header_t)); //先将包头读出
memcpy(Body, m_Data + sizeof(packet_header_t), sizeof(Body));
memcpy(&this->Tail, m_Data + sizeof(packet_header_t) + sizeof(Body), sizeof(packet_tali_t));

return true;

}

char* PacketBase::getBody() {
return Body;
}

packet_header_t* PacketBase::getHead() {
return &Head;
}

packet_tali_t* PacketBase::getTail() {
return &Tail;
}

char* PacketBase::getData() {
return m_Data;
}

int PacketBase::getSize() {
return m_Size;
}

//这个给解包用
void PacketBase::setSize(int size) {
this->m_Size = size;
this->Body_Size = size - sizeof(packet_header_t) - sizeof(packet_tali_t);
}

//这个给封包用
void PacketBase::setBodySize(int bodysize) {
this->Body_Size = bodysize;
this->m_Size = Body_Size + sizeof(packet_header_t) + sizeof(packet_tali_t);
}

//这个不知道干嘛用,历史遗留
PacketBase& PacketBase::operator =(const PacketBase& packet)
{
memset(m_Data, 0, MAX_PACKET_LENTH);
if (m_Size != packet.m_Size)
{
m_Size = packet.m_Size;
}
memcpy(m_Data, packet.m_Data, packet.m_Size);
return *this;
}
//自定义协议包
#pragma once
/************业务层数据包体************/

//客户端登录请求包
typedef struct login
{
int id;
int pwd; //密码
}Login_t;

//登录应答包
typedef struct res_login_st
{
int login_ret; //登录结果: 1-登录成功,0-登录失败
int dir_id; //初始文件列表id
}res_login_t;

//客户端注册请求包
typedef struct Register
{
int id; //账号
char tel[12]; //11位手机号
int pwd; //密码
}Register_t;

//注册应答包
typedef struct res_register_st
{
int register_ret; //注册结果: 0-注册成功,1-注册失败
}res_register_t;

//客户端修改密码请求包
typedef struct Change_PWD
{
int id; //账号
int pwd; //密码
}c_pwd_t;

//改密码应答包
typedef struct res_changepwd_st
{
int change_ret; //改密码结果: 0-改密码成功,1-改密码失败
}res_cpwd_t;

//找回密码请求包
typedef struct findpwd
{
int id;
int tel[12];
}F_Pwd_t;

//找回密码应答包
typedef struct res_findpwd_st
{
int find_ret; //找回结果: 0-找回成功,1-找回失败
int pwd; //密码
}res_fpwd_t;

//销户请求包
typedef struct deluser
{
int id;
int pwd;
}D_user_t;


/**********************************文件相关****************************************/

//上传文件请求包
typedef struct UpFile
{
int user_id;
int dir_id;
int mode; //文件权限位
int pwd;
char* file_name;
}UpFile_t;

//下载文件请求包
typedef struct Download_File
{
int user_id; //用户ID
int pwd;
char* file_name; //文件id
}Download_t;

//文件分享
typedef struct Cmode
{
int id;
int pwd;
int mode;
int yaoqingma; //邀请码
char* file_name;
}C_mode_t;

//新建目录
typedef struct AddFileList
{
int id;
int pwd;
int father_dir; //挂载在哪一级目录底下
char* dirname;
}A_filelist_t;

//修改文件目录
typedef struct CFileList
{
int id;
int pwd;
int old_dir;
int new_dir;
char* file_name;
}C_filelist_t;


//删除文件
typedef struct delfile
{
int id;
int pwd;
char* file_name;
}D_file_t;

//删除目录
typedef struct dellist
{
int id;
int pwd;
int dir_id;
} D_list_t;

//文件、目录总应答
typedef struct res_fl
{
int stata; //0成1败
}res_fl_t;

//文件列表请求包
typedef struct File_List
{
int user_id; //用户ID
int pwd;
int dir_id; //目录id
}FileList_t;

//文件列表应答包
typedef struct Res_VideoList
{
char V[800];
}res_filelist_t;

//心跳处理
typedef struct Heart
{
int heart; //占位
}res_heart_t;
//packet_command.h
#pragma once
#include "PacketBase.h"
#include "Packet1.h"

class PacketCommand1:protected PacketBase
{
public:
PacketCommand1();

bool replyLogin(int state,int dir_id, int fd);
bool replyRegist(int state, int fd);
bool replyCpwd(int state, int fd);
bool replyFpwd(int state,int pwd, int fd);
bool replyFL(int state, int fd);
bool replyFileList(char* filelist, int fd);
};
//packet_command.cpp

#include "PacketCommand1.h"

PacketCommand1::PacketCommand1():PacketBase(){

}

bool PacketCommand1::replyLogin(int state, int dir_id,int fd) {
Head.funcId = 0x01;
Head.optid = 0x01;
Head.fd = fd;
Head.usrlenth = sizeof(Body); //谁开的包谁封回去,所以大小是相对静止了
Head.syn = 0x04;

res_login_t* body = (res_login_t*)Body;
body->login_ret = state;
body->dir_id = dir_id;

Tail.pack_tail = 0x05;

return this->pack();
}

bool PacketCommand1::replyRegist(int state, int fd) {
Head.funcId = 0x02;
Head.optid = 0x01;
Head.fd = fd;
Head.usrlenth = sizeof(Body);
Head.syn = 0x04;

res_register_t* body = (res_register_t*)Body;
body->register_ret = state;

Tail.pack_tail = 0x05;

return this->pack();
}


bool PacketCommand1::replyFpwd(int state, int pwd, int fd) {
Head.funcId = 0x03;
Head.optid = 0x01;
Head.fd = fd;
Head.usrlenth = sizeof(Body);
Head.syn = 0x04;

res_fpwd_t* body = (res_fpwd_t*)Body;
body->find_ret = state;
body->pwd = pwd;

Tail.pack_tail = 0x05;

return this->pack();
}


bool PacketCommand1::replyCpwd(int state, int fd) {
Head.funcId = 0x04;
Head.optid = 0x01;
Head.fd = fd;
Head.usrlenth = sizeof(Body);
Head.syn = 0x04;

res_cpwd_t* body = (res_cpwd_t*)Body;
body->change_ret = state;

Tail.pack_tail = 0x05;

return this->pack();
}


bool PacketCommand1::replyFL(int state, int fd) {
Head.funcId = 0x15;
Head.optid = 0x01;
Head.fd = fd;
Head.usrlenth = sizeof(Body);
Head.syn = 0x04;

res_fl_t* body = (res_fl_t*)Body;
body->stata = state;

Tail.pack_tail = 0x05;

return this->pack();
}

bool PacketCommand1::replyFileList(char* filelist, int fd) {
Head.funcId = 0x11;
Head.optid = 0x01;
Head.fd = fd;
Head.usrlenth = sizeof(Body);
Head.syn = 0x04;

res_filelist_t* body = (res_filelist_t*)Body;
memcpy(body->V,filelist,sizeof(filelist));

Tail.pack_tail = 0x05;

return this->pack();
}

数据库模块修改

对数据库模块测试之后,做了几个修改,这里主要列几个

//DB_base.cpp

//获取查询记录中第n个数据(数据需有效)
int DB_base::ireturn_serch(char* sql, int n)
{
char* errMsg;
char** dbResult;
int nRow = 0, nColumn = 0;
int rc;

int result;
rc = sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
if (nRow == 0 || dbResult[nColumn + n - 1] == NULL) {
return 0; //如果没有数据,返回0
}

if (rc == SQLITE_OK && n <= nColumn)
{
result = atoi(dbResult[nColumn + n - 1]);
sqlite3_free_table(dbResult);
return result;
}
else
{
cout<<nColumn<<endl<<nRow<<endl;
cout << "ireturn_serch" << endl;
return NULL;
}
}

//返回多个结果,以ret参数形式返回
void DB_base::ret_any(char* sql,char* ret) {
char* errMsg;
char** dbResult;
int nRow = 0, nColumn = 0;
int rc;

int result;

rc = sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);

if (rc == SQLITE_OK){
for (int count = nColumn; count < (nRow * (nColumn + 1)); count++) {
strcat(ret,dbResult[count]);
}
}
else
cout << "ret_any" << endl;
}
//DB_command.cpp

//获取文件列表下所有目录、文件
void DB_command::file_list(int user_id, int pwd, int dir_id, char* ret){
if (login(user_id, pwd)) {
char* sql = new char[120];
memset(sql,0,120);
sprintf(sql, "select file_name from FileMsg where owner_id = %d and dir_id = %d", user_id, dir_id);
My_DB->ret_any(sql, ret);
sprintf(sql, "select dir_name from DirMsg where grade = %d",dir_id);
My_DB->ret_any(sql, ret);
delete sql;
}
else
cout << "can't get file list" << endl;
}

今日计划

原计划

测试代码:解压包模块与epoll模型

实际计划

由于应邀出席某个毕业班的评审嘉宾,所以下午就没时间了。所以今天将epoll模块也设计好,尽量争取把代码也敲了。

这两个模块的测试只能留待明天了,因为测试是未知数,谁也不知道会测出什么问题来。

一定是可以实现的!!!

FTP文件管理项目(本地云)项目日报(四)_.net_02