c++ - 如何将 vector 序列化为字符数组

标签 c++ serialization vector winsock

我有一个 vector 定义为:

std::vector<message *>

消息在哪里:

struct message{
    static unsigned int last_id;
    unsigned int id;
    std::string msg;
    std::string timestamp;
}

我的目标是使用 Winsock 发送此信息(从服务器到客户端),但这只允许发送出现在 WinSock2.h 中的字符。考虑到这一点,我想序列化一个字符数组中的所有信息(id、msg 和时间戳),以便将它们一起发送,并且在客户端中,具有反序列化的功能,以便具有相同的 vector I在服务器中。

我该如何实现?

感谢任何帮助。

最佳答案

下面提供了一种解决序列化问题的简单方法。

但是,请注意它不可移植。它假定双方(客户端/服务器)具有相同的环境条件,即字节序和 sizeof int 和 size_t。在编写服务器/客户端程序时,这种假设可能不能令人满意,您的代码也应该处理这方面的问题。

例如,如果您可以说 32 位足以满足 id 值和字符串长度的要求,则可以使用 htonl序列化时,ntohl反序列化时。

序列化器:

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

关于c++ - 如何将 vector 序列化为字符数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36515824/

相关文章:

c++ - 前向声明是否修复了参数的数量?

c++ - std::fclose() 的一个非常奇怪的问题

C# 无法捕获 SerializationException

c++ - 从 C++ 中的指针数组向 vector 添加元素

c++ - push_back() 是否总是增加 vector 的大小?

c++ - 编译器警告使 int8_t 的复合赋值提升为 int 感到困惑

c++ - std::thread 和 std::cin 在 opengl 应用程序中的输入

c# - WCF 错误 'There was an error while trying to serialize parameter...'

c# - 使用 Message.GetBody<> 时,仅根据请求反序列化根对象

c++ - 如何从 std::vector 搜索并返回项目