程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 最簡單的TCP網絡封包解包(補充)-序列化

最簡單的TCP網絡封包解包(補充)-序列化

編輯:關於C語言

如若描述或者代碼當中有謬誤之處,還望指正。

將數據能夠在TCP中進行傳輸的兩種方法
1.直接拷貝struct就可以了;
2.序列化。

拷貝Struct存在的問題
1.不能應付可變長類型的數據,比如STL中的那些容器,當然,STL的容器歸根到底就是一個class,他們的長度都是不確定的;
2.內存對齊的問題,Windows默認的對齊是4字節,如果不去刻意關閉掉對齊的話,那麼可能會多出不少沒必要的字節數,但是如果關閉了,內存拷貝又會慢一些。

序列化是怎麼序列化的?
其實很簡單,我們使用一個uint8類型的數組,假設我們這裡有一個uint16類型的數據,那麼我們就把它拷貝進去uint8的數組裡面,那麼它就占了兩個元素。這是最基本的規則。具體請參考代碼裡面的ByteBuffer::append()方法。而那些class神馬的,我們只要按照自己設定的規則順序拷貝進去就可以了。這個在BytBuffer裡面默認支持了常用的STL容器,可以參看代碼。

類型定義
#if defined(_MSC_VER)
    //
    // Windows/Visual C++
    //
    typedef signed __int8            int8;
    typedef unsigned __int8            uint8;
    typedef signed __int16            int16;
    typedef unsigned __int16        uint16;
    typedef signed __int32            int32;
    typedef unsigned __int32        uint32;
    typedef signed __int64            int64;
    typedef unsigned __int64        uint64;
#endif有的類型的長度會因硬件或者操作系統而異,如果直接使用c++關鍵字中的類型定義可能會出現問題。因此,需要自己定義以上這樣的類型。利用宏去適配各個操作系統或者硬件平台。

ByteBuffer的代碼
/**///////////////////////////////////////////////////////////////////////////
/// 字節流緩沖類,可以進行序列化和解序列化操作,並且可以緩沖字節流數據。
//////////////////////////////////////////////////////////////////////////
class ByteBuffer
{
public:
    const static size_t DEFAULT_SIZE = 0x1000;

    ByteBuffer()
        : mReadPos(0)
        , mWritePos(0)
    {
        mStorage.reserve(DEFAULT_SIZE);
    }

    ByteBuffer(size_t res)
        : mReadPos(0)
        , mWritePos(0)
    {
        mStorage.reserve(res);
    }

    ByteBuffer(const ByteBuffer &buf)
        : mReadPos(buf.mReadPos)
        , mWritePos(buf.mWritePos)
        , mStorage(buf.mStorage)
    {}

    /**///////////////////////////////////////////////////////////////////////////
public:
    void clear()
    {
        mStorage.clear();
        mReadPos = mWritePos = 0;
    }

    template <typename T>
        void append(T value)
    {
        append((uint8*)&value, sizeof(value));
    }

    template <typename T>
        void put(size_t pos, T value)
    {
        put(pos, (uint8*)&value, sizeof(value));
    }

    /**///////////////////////////////////////////////////////////////////////////
public:
    ByteBuffer& operator<<(bool value)
    {
        append<char>((char)value);
        return *this;
    }
    ByteBuffer& operator<<(uint8 value)
    {
        append<uint8>(value);
        return *this;
    }
    ByteBuffer& operator<<(uint16 value)
    {
        append<uint16>(value);
        return *this;
    }
    ByteBuffer& operator<<(uint32 value)
    {
        append<uint32>(value);
        return *this;
    }
    ByteBuffer& operator<<(uint64 value)
    {
        append<uint64>(value);
        return *this;
    }

    ByteBuffer& operator<<(int8 value)
    {
        append<int8>(value);
        return *this;
    }
    ByteBuffer& operator<<(int16 value)
    {
        append<int16>(value);
        return *this;
    }
    ByteBuffer& operator<<(int32 value)
    {
        append<int32>(value);
        return *this;
    }
    ByteBuffer& operator<<(int64 value)
    {
        append<int64>(value);
        return *this;
    }

    ByteBuffer& operator<<(float value)
    {
        append<float>(value);
        return *this;
    }
    ByteBuffer& operator<<(double value)
    {
        append<double>(value);
        return *this;
    }
    ByteBuffer& operator<<(time_t value)
    {
        append<time_t>(value);
        return *this;
    }

    ByteBuffer& operator<<(const std::string& value)
    {
        append((uint8 const *)value.c_str(), value.length());
        append((uint8)0);
        return *this;
    }
    ByteBuffer& operator<<(const char* str)
    {
        append( (uint8 const *)str, str ? strlen(str) : 0);
        append((uint8)0);
        return *this;
    }

    /**//////////////////////////////////////////////

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved