如若描述或者代碼當中有謬誤之處,還望指正。
將數據能夠在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;
}
/**//////////////////////////////////////////////