将 QByteArray 反序列化为多个 QVariantMap

Deserializing QByteArray to multiple QVariantMap's

我正在为 IPC 使用 QTcpSockets。我以为 QTcpSocket readyReady 信号发射有问题。结果我遇到了 QTcpSocket 缓冲问题。

在正常情况下,有一段非常简单的代码可以将 QByteArray 反序列化为 QVariantMap

    // Init Last Buffer
    QByteArray lastBuffer;

    // ...

    // Init New Data Stream
    QDataStream newDataStream(lastBuffer);
    // Init Last Data Map
    QVariantMap lastDataMap;        

    // Clear Last Variant Map
    lastDataMap.clear();

    // Red Data Stream To Data Map
    newDataStream >> lastDataMap;

一切都很好,直到我快速发送了很多包裹。结果 QTcpSocket 将它们打包成更大的包。有时我将所有数据接收到一个 QByteArray 中,有时分别放入不同大小的包中,绝对不是另一边包实际 written/sent 的方式。

我的问题是:你们中有人遇到过同样的问题吗?已经有解决方案了吗?你能推荐一个好的解决方案吗?

当然我可以去挖掘所有相关的 Qt 源代码,但我的观点是在我的项目中有一个简单但足够复杂的解决方案来重用现有的 Qt 组件,只需在定制、开发和变化。创新 ; )

谢谢大家!

你的问题是因为 TCP 是一种流协议,这意味着数据将以不同的块到达你的计算机,并在新块到达时呈现给你的应用程序。 QTcpSocket 符合此规范,因此无法保证当它发出数据已到达的信号时,数据就是完整的。

不幸的是,QDataStream 假设它正在读取的设备包含一组完整的数据。如果 QDataStream 没有数据可读,它会以未定义的结果退出,不会等待下一个 QVariant 完成下载。

因此,您不能像在其他具有完整数据集的设备(例如 QFile)上那样在 QTcpSocket 上使用 QDataStream

您需要在程序中构建额外的处理程序以检查是否有足够的数据到达进行解析。

如果您查看 Fortune Client 和 Fortune Server 示例的文档,您会发现它们首先使用 QDataStream 将数据序列化为 QByteArray,然后将通过网络发送时的数据大小。

客户端首先等待足够的数据到达读取数据流的大小,然后它一直将传入的数据存储在QByteArray中,直到一切都到达后再交给QDataStream 用于解析。

如果你不是每次都传输大量数据,或者你很高兴你有足够的内存资源暂时将数据保存在 QByteArray 中,直到它准备好已解析。

如果您需要在数据传入时进行解析,建议您创建自己的自定义协议以通过网络流式传输,而不是 QDataStream。