Ниже приведен простой подход к проблеме сериализации.
Однако обратите внимание, что не переносится. Он принимает одинаковые условия среды с обеих сторон (клиент/сервер), то есть endianness и sizeof int и size_t. Это предположение, вероятно, неудовлетворительно при написании программ сервера/клиента, и ваш код также должен обрабатывать этот аспект.
Например, если вы можете сказать, что 32 бит является достаточным размером для значения id
и длиной ваших строк, вы можете использовать htonl при сериализации и ntohl при десериализации.
Serializer:
class MessageSerializer
{
public:
MessageSerializer(const message& messageStruct)
: m_msgRef(messageStruct)
, m_msgLength(m_msgRef.msg.length())
, m_timeLength(m_msgRef.timestamp.length())
{}
size_t RequiredBufferSize() const
{
return sizeof(int) + sizeof(size_t)*2 + m_msgLength + m_timeLength;
}
void Serialize(void* buffer) const
{
PushNum (buffer, m_msgRef.id);
PushString (buffer, m_msgRef.msg.c_str(), m_msgLength);
PushString (buffer, m_msgRef.timestamp.c_str(), m_timeLength);
}
private:
const message& m_msgRef;
const size_t m_msgLength;
const size_t m_timeLength;
template<typename INTEGER>
void PushNum(void*& buffer, INTEGER num) const
{
INTEGER* ptr = static_cast<INTEGER*>(buffer);
//copying content
*ptr = num;
//updating the buffer pointer to point the next position to copy
buffer = ++ptr;
}
void PushString(void*& buffer, const char* cstr, size_t length) const
{
PushNum(buffer, length);
//copying string content
memcpy(buffer, cstr, length);
//updating the buffer pointer to point the next position to copy
char* ptr = static_cast<char*>(buffer);
ptr += length;
buffer = ptr;
}
};
десериализатор:
class MessageDeserializer
{
public:
MessageDeserializer(const char* messageBuffer)
: m_msgBuffer(messageBuffer)
{}
void Deserialize(message& messageOut)
{
messageOut.id = PopNum<int>(m_msgBuffer);
messageOut.msg = PopString(m_msgBuffer);
messageOut.timestamp = PopString(m_msgBuffer);
}
private:
const void* m_msgBuffer;
template<typename INTEGER>
INTEGER PopNum(const void*& buffer) const
{
const INTEGER* ptr = static_cast<const INTEGER*>(buffer);
//copying content
INTEGER retVal = *ptr;
//updating the buffer pointer to point the next position to copy
buffer = ++ptr;
return retVal;
}
std::string PopString(const void*& buffer) const
{
size_t length = PopNum<size_t>(buffer);
const char* ptr = static_cast<const char*>(buffer);
//copying content
std::string retVal(ptr, length);
//updating the buffer pointer to point the next position to copy
ptr += length;
buffer = ptr;
return retVal;
}
};
Тогда ваш используя код может быть что-то вроде:
//...
MessageSerializer serializer(*myVector[i]);
char* buffer = new char[serializer.RequiredBufferSize()];
serializer.Serialize(buffer);
и:
//...
message myMsg;
MessageDeserializer(input).Deserialize(myMsg);
Пожалуйста, просмотрите [MCVE]. Можете ли вы показать, что вы пробовали? –
Я искал множество способов его реализации, но я не нашел подходящего решения. Любой ключевой факт для начала сериализации будет оценен по достоинству. – Zarauztarra
Я не знаком с Winsock, но, вероятно, подобен тому, что я использовал. Представьте, что все 4 из ваших предметов «уплотнены» в один вектор символов (я использую std :: string). Как пункт назначения найдет отдельные поля? Возможно, протокол вашего собственного изобретения? A (несколько) связанная область называется «постоянным хранилищем», я считаю, что некоторые пакеты существуют, но не помнят имя. Удачи. –