1

我想通过 QUdpSocket 发送一个结构。我知道我应该使用QDataStreamand QByteArray,但我不能,因为接收者不会使用 Qt。

我尝试了很多东西,但我从来没有找到似乎可以正常工作的东西。

我的结构将是:

typedef struct myStruct
    {
       int nb_trame;
       std::vector<bool>  vBool;
       std::vector<int>   vInt;
       std::vector<float> vFloat;
    } myStruct;

我该如何正确地做到这一点?

4

1 回答 1

3

解决此问题的方法称为序列化

序列化是将数据结构或对象状态转换为可以存储(例如,在文件或内存缓冲区中,或通过网络连接链路传输)并稍后在相同或另一个计算机环境中重建的格式的过程。

以下是如何使用 QDataStream 序列化上述结构的完整示例:

// main.cpp
#include <limits>
#include <QDataStream>
#include <QVector>
#include <vector>

typedef struct myStruct
{
   int nb_trame;
   std::vector<bool>  vBool;
   std::vector<int>   vInt;
   std::vector<float> vFloat;

   void serialize(QDataStream &out) {
       out << nb_trame;
       out << QVector<bool>::fromStdVector(vBool);
       out << QVector<qint32>::fromStdVector(vInt);
       out << QVector<float>::fromStdVector(vFloat);
   }
} myStruct;

void fillData(myStruct &s) {
    s.nb_trame = 0x42;

    s.vBool.push_back(true);
    s.vBool.push_back(false);
    s.vBool.push_back(false);
    s.vBool.push_back(true);

    s.vInt.push_back(0xB0);
    s.vInt.push_back(0xB1);
    s.vInt.push_back(0xB2);
    s.vInt.push_back(0xB3);

    s.vFloat.push_back(std::numeric_limits<float>::min());
    s.vFloat.push_back(0.0);
    s.vFloat.push_back(std::numeric_limits<float>::max());
}

int main()
{
    myStruct s;

    fillData(s);

    QByteArray buf;
    QDataStream out(&buf, QIODevice::WriteOnly);
    s.serialize(out);
}

然后你可以buf发送QUdpSocket::writeDatagram()


如何QDataStream序列化

如果我们更换

QByteArray buf;
QDataStream out(&buf, QIODevice::WriteOnly);

QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);

序列化的数据被写入文件“file.dat”。这是上面的代码生成的数据:

> hexdump -C file.dat
00000000  00 00 00 42 00 00 00 04  01 00 00 01 00 00 00 04  |...B............|
00000010  00 00 00 b0 00 00 00 b1  00 00 00 b2 00 00 00 b3  |................|
00000020  00 00 00 03 38 10 00 00  00 00 00 00 00 00 00 00  |....8...........|
00000030  00 00 00 00 47 ef ff ff  e0 00 00 00              |....G.......|
  • 数据以四个字节开始,代表成员 nb_trame ( 00 00 00 42)
  • 接下来的八个字节是向量 vBool ( 00 00 00 04 01 00 00 01) 的序列化形式
    • 00 00 00 04--> 向量中的条目数
    • 01 00 00 01--> 真、假、假、真
  • 接下来的 20 个字节用于 vInt ( 00 00 00 04 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3)
    • 00 00 00 04--> 向量中的条目数
    • 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3--> 0xB0、0xB1、0xB2、0xB3(每个条目 4 个字节)
  • 接下来的 28 个字节用于 vFloat ( 00 00 00 03 38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00)
    • 00 00 00 03--> 向量中的条目数
    • 38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00--> 1.1754943508222875e-38, 0.0, 3.4028234663852886e+38(每个条目8字节)

附加信息(原始发布)

序列化不是一个微不足道的话题,但是那里有很多库可以帮助您。最后,您有两种选择:

  1. 定义自己的序列化格式
  2. 使用现有的序列化格式
    1. 二进制
    2. 基于文本(例如 JSON、XML)

您选择哪一个在很大程度上取决于您的需求和用例。一般来说,我更喜欢已建立的格式而不是自酿。基于文本的格式本质上不太紧凑,需要更多空间,因此也需要带宽。这是您在决定格式时应该考虑的因素。另一方面,基于文本/人类可读的格式具有更容易调试的优点,因为您可以在文本编辑器中打开它们。还有更多你应该考虑的因素。

序列化之所以有效,是因为您不依赖于机器相关的事物。您唯一需要注意的是序列化数据是一致的并遵循定义的格式。因此,对于序列化数据,您确切地知道字节顺序是如何定义的,特定数据的存储位置等等。

这个想法是发送方序列化数据,通过任何需要的通道发送,接收方再次反序列化数据。数据以哪种格式存储在双方的每一方都无关紧要。

   +--------------------------------+             +--------------------------------+
   | Host A                         |             | Host B                         |
   |                                |             |                                |
   |                                |             |                                |
   |                                |             |                                |
   |  +-------------------------+   |             |  +-------------------------+   |
   |  |         Raw data        |   |             |  |         Raw data        |   |
   |  |(Specific to plattfrom A)|   |             |  |(Specific to plattfrom B)|   |
   |  +-------------------------+   |             |  +-------------------------+   |
   |               |                |             |               ^                |
   |               | serialize      |             |               | deserialize    |
   |               v                |             |               |                |
   |      +-----------------+       |  transmit   |      +-----------------+       |
   |      | Serialized Data +----------------------------> Serialized Data |       |
   |      +-----------------+       |             |      +-----------------+       |
   |                                |             |                                |
   +--------------------------------+             +--------------------------------+
于 2016-05-26T14:56:31.247 回答