If there are errors in the description or code, I hope to correct them.
Two Methods for transmitting data in TCP
1. Copy struct directly;
2. serialization.
Problems with copying Struct
1. cannot cope with variable-length data, such as those containers in STL. Of course, STL containers are actually a class and their lengths are uncertain;
2. memory alignment problem. The default alignment in Windows is 4 bytes. If you do not deliberately disable alignment, there may be many unnecessary bytes, but If you disable alignment, memory copying slows down.
How is serialization made?
In fact, it is very simple. We use a uint8 type array. Suppose we have a uint16 type data here, then we copy it into the uint8 array, then it occupies two elements. This is the most basic rule. For details, refer to the ByteBuffer: append () method in the code. However, we only need to copy the class in the sequence set by ourselves. BytBuffer supports common STL containers by default. For more information, see the code.
Type Definition
# 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;
# The length of some endif types varies depending on the hardware or operating system. If you directly use the type definition in the c ++ keyword, problems may occur. Therefore, you need to define the above types. Use macros to adapt to various operating systems or hardware platforms.
ByteBuffer code
/**///////////////////////////////////// //////////////////////////////////////
/// Byte stream buffer class, which can be serialized and deserialized, and can buffer byte stream data.
//////////////////////////////////////// //////////////////////////////////
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;
}
/**///////////////////////////////////// /////////