将 QByteArray 反序列化为多个 QVariantMap的

Deserializing QByteArray to multiple QVariantMap's

本文关键字:QVariantMap QByteArray 反序列化      更新时间:2023-10-16

我正在为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中,有时单独接收到不同大小的包中,这绝对不是在另一端实际写入/发送包的方式。

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

当然,我可以去挖掘所有相关的Qt源代码,但我的重点是在我的项目中,只要在定制、开发和更改方面投入合理的精力,就可以获得一个简单但足够复杂的解决方案,重用现有的Qt组件。创新;)

谢谢大家!

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

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

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

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

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

客户端首先等待,直到有足够的数据到达以读取数据流的大小,然后将传入的数据存储在QByteArray中,直到所有数据都到达,然后将其移交给QDataStream进行解析。

如果您不是每次都传输大量数据,或者您很高兴有足够的内存资源将数据临时保存在QByteArray中,直到数据准备好被解析,那么这种方法就很好了。

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