我正在尝试通过 TCP 链接传输 Cereal 的序列化结果(二进制存档)。对于接收方来说,第一件事是决定恢复消息对象需要多少字节(至少),但似乎没有办法获得这些信息。
具有所有原始类型成员的结构的序列化结果似乎与结构大小的结果一样大。对此有任何保证吗?我很担心,因为如果由便携式二进制存档序列化,结果会大 1 个字节。我知道这是为了记录字节序,但是接收方怎么知道呢?我想出的唯一安全方法是序列化消息并从输出流中获取大小。对于接收方来说,这看起来并不那么优雅。
我正在尝试通过 TCP 链接传输 Cereal 的序列化结果(二进制存档)。对于接收方来说,第一件事是决定恢复消息对象需要多少字节(至少),但似乎没有办法获得这些信息。
具有所有原始类型成员的结构的序列化结果似乎与结构大小的结果一样大。对此有任何保证吗?我很担心,因为如果由便携式二进制存档序列化,结果会大 1 个字节。我知道这是为了记录字节序,但是接收方怎么知道呢?我想出的唯一安全方法是序列化消息并从输出流中获取大小。对于接收方来说,这看起来并不那么优雅。
我自己找到了解决方案。在这里分享,以防它对其他人也有用。
获取大小的最可靠方法是实际序列化数据,所以我所做的是避免序列化期间通常的内存分配/访问开销(使用 std::stringstream 时)。
解决方案从 std::basic_streambuf<> 派生开始(对于 Cereal,它必须是 std::streambuf)
class COUNTER_BUFFER : public std::streambuf
{
private :
size_t mSize = 0;
private :
int_type overflow(int_type C)
{
return mSize++;
}
public :
size_t Size(void) const
{
return mSize;
}
};
通常从 std::basic_streambuf 派生的类应该将字符写入某个缓冲区(文件、字符串等),但这里它计算写入了多少字符(字节)。
下一步为 std::basic_ostream 分配一个实例,该实例从 Cereal 传递到存档:
COUNTER_BUFFER Buffer;
std::basic_ostream<char> Stream(&Buffer);
cereal::BinaryOutputArchive Archive(Stream);
正常序列化任何数据结构,完成后,调用 Buffer.Size() 获取大小。
对于仅包含原始类型的数据结构,应该有一种方法可以在编译时获取序列化大小,但是使用这种非最佳方法我只能在运行时获取它。
这对我来说已经足够好了。