我以这种方式使用booost序列化:
Header H(__Magic, SSP_T_REQUEST, 98, 72, 42, Date(), SSP_C_NONE);
Header Z;
std::cout << H << std::endl;
std::cout << std::endl;
char serial_str[4096];
std::memset(serial_str, 0, 4096);
boost::iostreams::basic_array_sink<char> inserter(serial_str, 4096);
boost::iostreams::stream<boost::iostreams::basic_array_sink<char> > s(inserter);
boost::archive::binary_oarchive oa(s);
oa & H;
s.flush();
std::cout << serial_str << std::endl;
boost::iostreams::basic_array_source<char> device(serial_str, 4096);
boost::iostreams::stream<boost::iostreams::basic_array_source<char> > s2(device);
boost::archive::binary_iarchive ia(s2);
ia >> Z;
std::cout << Z << std::endl;
它完美无缺。
然而,我需要在套接字上发送这些数据包。我的问题是,我怎么知道在另一边需要读多少字节?序列化结果的大小不是常数,btw大于我的struct的sizeof。
如何确保数据在另一方面完整?我使用循环缓冲区,但序列化怎么办?
全部
答案 0 :(得分:1)
一般来说,无法预测。它(很多)取决于存档格式。但是通过对象跟踪,可以省略子图,并且通过动态类型信息可以添加大量数据。
如果您可以为序列化数据提供暂存缓冲区,则可以先将序列化为缓冲区,然后在发送有效负载之前发送大小(现在就知道了)。
会有开销
以下是一些答案,为您提供有关这些调整点的更多信息:
如果您的所有数据都是POD,则很容易预测大小。
如果您在同一台机器上共享IPC,并且您已经在使用循环缓冲区,请考虑将循环缓冲区放入共享内存中。
我有很多答案(搜索managed_shared_memory
或managed_mapped_file
)并举例说明。
一个具体的例子,关注一个无锁的单一生产者/单一消费者场景:Shared-memory IPC synchronization (lock-free)
即使您选择/需要流式传输消息(例如通过网络),您仍然可以使用例如Managed External Buffers。因此,即使不要求所有数据都是POD,您也可以避免执行任何序列化。 (诀窍在于内部,使用offset_ptr<>
而不是原始指针,使所有引用相对)。
答案 1 :(得分:-1)
创建自己的流式类并覆盖xsputn
方法。
class counter_streambuf : public std::streambuf {
public:
using std::streambuf::streambuf;
size_t size() const { return m_size; }
protected:
std::streamsize xsputn(const char_type* __s, std::streamsize __n) override
{ this->m_size += __n; return __n; }
private:
size_t m_size = 0;
};
用法:
Header H(__Magic, SSP_T_REQUEST, 98, 72, 42, Date(), SSP_C_NONE);
counter_streambuf csb;
boost::archive::binary_oarchive oa(csb, boost::archive::no_header);
oa & H;
cout<<"Size: "<<csb.size();