我有一个小层次的对象,我需要序列化和传送通过一座连接。我需要两个序列化的目的,然后deserialize它基于什么类型。是否有一个简单的方法来做到这一点在C++(如有Java)?

是否有任何C++化网络代码样本或教程?

编辑: 只是要清楚,我正在寻找方法上的转化对象为一系列的字节,然后回到一个对象。我可以把手插座传输。

有帮助吗?

解决方案

谈系列化,提高系列化API 在我脑海中。至于过网发送该串行化的数据,我要么使用Berkeley套接字或 ASIO库

修改结果 如果你想你的序列化对象的字节数组,你可以使用以下方式提升串行器(从教程网站获取):

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
class gps_position
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;

public:
    gps_position(){};
    gps_position(int d, int m, float s) :
    degrees(d), minutes(m), seconds(s)
    {}
};

实际序列化然后很容易:

#include <fstream>
std::ofstream ofs("filename.dat", std::ios::binary);

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    {
        boost::archive::binary_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
        // archive and stream closed when destructors are called
    }

反序列化工作在类似的方式。

还有一些让你处理指针序列(如发绺等复杂的数据结构都没有问题),派生类并且可以二进制和文本串行化之间进行选择的机制。除了所有STL容器被支撑开箱。

其他提示

在某些情况下,在处理简单的类型,你可以这样做:

object o;
socket.write(&o, sizeof(o));

这是确定的作为一个概念证明或一份草案,那么你的团队的其他成员可以继续工作在其他部分。

但是或早或晚, 通常早, 这会让你受伤了!

你碰到的问题有:

  • 虚拟表指针将被破坏。
  • 指针(数据,成员/职能)将被破坏。
  • 差异填充/取向不同的机。
  • 大/Little-Endian byte订购的问题。
  • 变化的执行情况的浮/倍。

(再加上你需要知道你是什么拆成的接收方。)

你可以改进这种通过发展自己的调动/解组方式为每一类。(理想的是虚拟的,所以他们可以延长中的子类。) 一些简单的宏会让你写出了不同基本类型很快在一个大/little-endian中立的秩序。

但是,这种繁重的工作要好得多,并且更容易处理,处理通过 提升的化图书馆.

序列化装置将你的对象为二进制数据。而反序列化是指从数据重新创建的对象。

当序列化您正在推动字节到uint8_t载体。 当反序列化要从uint8_t矢量读取字节。

有一定序列化的东西时,你可以使用的模式。

每个序列化类应该具有serialize(std::vector<uint8_t> &binaryData)或类似signatured函数,将写入其二进制表示到提供的载体中。然后下降到它的部件的串行化的功能,这样他们可以写自己的东西把它太此函数可以通过这个载体中。

由于数据表示可以是在不同的体系结构不同。 你需要找出一个方案如何表示的数据。

让我们从基础开始:

序列化整数数据

刚写在小端排序的顺序字节。或者,如果尺寸事项使用varint表示。

序列化在小endian顺序:

data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);

从反序列化小endian顺序:

integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);

序列化浮点数据

据我所知道的IEEE 754具有垄断地位在这里。我不知道会用花车别的任何主流架构。这可能是唯一不同的是字节顺序。一些体系使用小尾数,其他人使用大端字节顺序。这意味着你需要大声其中以你要小心了在接收端的字节数。另一个不同之处可处理反规范和无限和NAN值。但只要你避免这些值,你应该确定。

序列化:

uint8_t mem[8];
memcpy(mem, doubleValue, 8);
data.push_back(mem[0]);
data.push_back(mem[1]);
...

反序列化向后做。注意你的架构的字节顺序!

序列化字符串

首先,你需要在一个编码一致。 UTF-8是常见的。然后将其存储为一个长度为前缀的方式:第一你使用我在上面提到的方法存储该字符串的长度,然后写该字符串逐字节

序列化阵列。

它们是相同的字符串。你第一序列表示该数组的大小然后序列化的每个对象在它的整数。

序列化对象整体

正如我说他们应该具有serialize方法将内容添加到载体之前。 反序列化对象,它应该有一个构造函数的字节流。它可以是一个istream但在简单的情况下,也可以只是一个参考uint8_t指针。构造函数读取它从流想要的字节并设置字段的对象。 如果系统被精心设计和序列化对象字段顺序的字段,你可以通过流场的构造函数中的初始化列表,并让他们在正确的顺序反序列化。

序列化的对象图

首先,你需要确保,如果这些对象是真的要序列东西。你并不需要序列化他们,如果这些对象的情况下,目前的目标。

现在你发现你需要序列由指针指向该对象。 指针它们是有效的只有在使用它们的程序的问题。你不能序列化指针,你应该停止在对象使用它们。相反,创建对象池。 该目的池基本上是一个动态数组,它包含“盒子”。这些盒子有一个引用计数。非零参考计数指示一个活对象,零指示空槽。然后创建智能指针类似,它不是存储指向对象shared_ptr的,但在数组中的索引。您还需要上表示空指针的指数,如同意。 -1。

基本上我们在这里做替换数组索引指针。 现在序列化时,你可以序列化此数组索引如常。您不必担心在什么地方objec吨将在目标系统上的存储器。只要确保它们具有相同的对象池了。

因此,我们需要序列化对象池。但哪些?那么,当你序列化,你不只是序列化对象的对象图,你是序列化整个系统。这意味着系统的系列化不应该从系统的部分开始。这些对象不应该担心系统的其余部分,他们只需要序列化数组索引,就是这样。你应该有一个系统的串行例程编排系统的系列化和走过的有关对象池和序列化所有的人。

在接收端的所有阵列内被反序列化的对象,再现所需的对象图。

序列化函数指针

不要存储指针在对象中。具有其中包含指向这些函数的静态数组,并存储在对象中的索引。

由于这两种方案都该表汇编成themshelves,仅使用索引应该工作。

序列化多态类型

由于我说你应该避免指针的序列化类型,你应该使用数组索引来代替,只是多态性不能工作,因为它需要的指针。

您需要与类型的变量和工会工作围绕此。

版本

在上述所有的顶部。您可能需要不同版本的软件互操作的。

在此情况下,每个对象应该在其序列的开始写入版本号以指示版本。

在另一侧加载了对象,新的对象,也许能处理旧的交涉,但旧的无法处理的新的所以他们应该抛出这个异常。

每当有新的变化,你应该碰到的版本号。


因此,为了这个包裹起来,串行化可能是复杂的。不过幸运的是,你并不需要在你的程序序列化的一切,经常只有协议消息被序列化,这往往是普通的旧结构。所以,你不需要复杂的技巧我上面也经常提到的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top