我想通过QUdpSocket发送一个结构。
我知道我应该使用QDataStream
和QByteArray
,但我不能,因为接收器不会使用Qt。
我尝试了很多东西,但我从来没有找到似乎正在做的工作正确。
我的结构将是:
typedef struct myStruct
{
int nb_trame;
std::vector<bool> vBool;
std::vector<int> vInt;
std::vector<float> vFloat;
} myStruct;
我如何正确正确?
答案 0 :(得分:3)
对此的解决方案称为serialization
序列化是将数据结构或对象状态转换为可以存储的格式(例如,在文件或内存缓冲区中,或通过网络连接链接传输)并稍后在相同或另一个计算机环境中重建的过程
以下是如何使用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.......|
00 00 00 42
)00 00 00 04 01 00 00 01
)的序列化形式
00 00 00 04
- &gt;向量中的条目数01 00 00 01
- &gt;真,假,假,真00 00 00 04 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3
)
00 00 00 04
- &gt;向量中的条目数00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3
- &gt; 0xB0,0xB1,0xB2,0xB3(每个条目4个字节)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
- &gt;向量中的条目数38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00
- &gt; 1.1754943508222875e-38,0.0,3.4028234663852886e + 38(每个条目8个字节)序列化不是一个简单的主题,但有很多库,可以帮助你。最后,您有两个选项可供选择:
您选择哪一个取决于您的需求和用例。总的来说,我更喜欢既定的格式而不是自酿。基于文本的格式本质上不那么紧凑,需要更多空间,因此也需要带宽。在决定格式时,您应该考虑这一点。另一方面,基于文本/人类可读的格式具有易于调试的优点,因为您可以在文本编辑器中打开它们。还有更多因素需要考虑。
序列化的工作原理是因为您不依赖于机器相关的东西。您唯一需要注意的是序列化数据是一致的并遵循定义的格式。因此,对于序列化数据,您确切地知道如何定义字节顺序,存储特定数据的位置等等。
这个想法是发送者序列化数据,通过任何需要的通道发送数据,接收器再次反序列化数据。数据以哪种格式存储在双方的每一方都没关系。
+--------------------------------+ +--------------------------------+
| Host A | | Host B |
| | | |
| | | |
| | | |
| +-------------------------+ | | +-------------------------+ |
| | Raw data | | | | Raw data | |
| |(Specific to plattfrom A)| | | |(Specific to plattfrom B)| |
| +-------------------------+ | | +-------------------------+ |
| | | | ^ |
| | serialize | | | deserialize |
| v | | | |
| +-----------------+ | transmit | +-----------------+ |
| | Serialized Data +----------------------------> Serialized Data | |
| +-----------------+ | | +-----------------+ |
| | | |
+--------------------------------+ +--------------------------------+