FTP文件管理項目(本地雲)項目日報(關於不定長包的測試)

第一次弄不定長包,大家都不太熟,網絡上又衆說紛紜,沒有一個完整代碼可以參考,所以我們走了不少的彎路。
昨天把解壓包模塊測試一遍,並進行了修訂(主要是隊員們很迫切的再問這個模塊到底要怎麼弄,不然我可能今天還在計劃)。

在這裏插入圖片描述

看,這個模塊,19號就寫好了,一直拖到12號才測。

接下來來看一下對比代碼:

關於原先解壓包模塊的設計圖和代碼在日報2中:FTP文件管理項目(本地雲)項目日報(二)
但是我要重新做個圖了。

舊圖:

在這裏插入圖片描述

新圖:

在這裏插入圖片描述

新舊對比

1、舊圖中使用的是兩個包對象完成一條服務,但是新包是一個對象,爲什麼呢?因爲之前我一直以爲包的body一旦分配內存之後,便固定住了,後來我發現,可以有以下操作:

char *a;
a = new char[10];
sprintf(a,"abcdefg");

a = new char[20];
sprintf(a,"abcdefghijklmn");

而上下兩塊內存是不衝突的,頂多是一點內存碎片,如果嚴謹一點,那就delete之後再new。
受到啓發,我將代碼進行修改,在解包時使用一塊不算大的內存(包體通常很小,大的是包頭),封包的時候再根據實際情況進行封包。

2、解包、封包時包體的偏移量。
之前用定長包的時候,對包的偏移就是sizeof(body),因爲那時候body是這樣定義的:char body[1024 - sizeof(head) - sizeof(tail)],所以sizeof(body)並沒有什麼問題,但是現在的body是不定長的,是這樣的:char* body; body = new char[sizeof(具體協議包)],那這時候情況就不一樣了,沒什麼特殊情況,指針大小都是4。關於這點,我調試了好一會兒纔想起來,爲什麼數據打印出來會丟哈哈哈,原來就寫了四個字節進去。

接着看一下代碼修改:

解壓包舊代碼:

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;
    
}

解壓包新代碼:

bool PacketBase::pack()
{
    memcpy(m_Data, &this->Head, sizeof(packet_header_t));
    memcpy(m_Data + sizeof(packet_header_t), this->Body, Body_Size); 
    memcpy(m_Data + sizeof(packet_header_t) + Body_Size, &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), Body_Size);
    memcpy(&this->Tail, m_Data + sizeof(packet_header_t) + Body_Size, sizeof(packet_tali_t));
 
    return true; 
}

注意加以區分。

具體協議包就代碼:

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::replyLogin(int state, int dir_id,int fd) {
//加了下面這幾行
    int sz = sizeof(res_login_t);
    this->setBodySize(sz);
    this->Body = new char[sz];

    Head.funcId = 0x01;
    Head.optid = 0x01;
    Head.fd = fd;
    Head.usrlenth = sz;	//還有這裏   
    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();
}

然後呢,放一個登陸包的測試代碼吧,因爲每個包的實現方式都一樣:

測試代碼:

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

using namespace std;

int main()
{
	PacketCommand1* pack1 = new PacketCommand1();	

	pack1->replyLogin(7, 9, 6);

	pack1->unpack();

	cout << pack1->getHead()->fd << endl;
	res_login_t *body = (res_login_t*)pack1->getBody();
	cout << body->dir_id << " " << body->login_ret << endl;
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章