QT 网络请求数据不全

QT 使用QNetworkReply对象发送get请求url,接收数据不全
情况描述:请求的数据包含两包,前面一个短包长度为L1(二三十个)个字节,后面是个长包长度为L2(大概7万)个字节,接收到读取数据通知后使用QNetworkReply对象调用了readall接口,数据总量只有L2,但是接收到的数据却是短包全部数据L1个字节+长包数据前面的(L2-L1)个字节,即长包末尾丢失了L1个字节,这种问题怎么解决?

出现这种问题的原因可能是因为网络传输过程中出现了数据包丢失或者网络延迟等问题。在这种情况下,建议使用QNetworkReply的readyRead信号和read函数来读取数据,而不是使用readAll函数。因为readAll函数只会读取当前可读取的所有数据,如果数据包分为多个部分到达,可能会导致数据丢失。

以下是一种可能的解决方法:

在发送请求时,设置QNetworkRequest的属性,使其支持分块传输。具体方法是在请求头中添加"Range"字段,指定需要请求的数据范围。例如,如果需要请求从第L1个字节到第L1+L2-1个字节的数据,可以设置"Range"字段为"bytes=L1-L1+L2-1"。

在处理readyRead信号时,使用read函数来读取数据。由于数据可能分为多个部分到达,需要在每次读取数据时将其累加到一个缓冲区中,直到缓冲区中的数据长度达到L2为止。如果数据长度不足L2,可以继续等待readyRead信号,直到读取到足够的数据。

以下是一段代码示例,用于实现以上解决方法:


lisp
Copy
// 发送请求
QNetworkRequest request(url);
request.setRawHeader("Range", QString("bytes=%1-%2").arg(L1).arg(L1+L2-1));
QNetworkReply *reply = manager.get(request);

// 处理readyRead信号
QByteArray buffer;
QDataStream in(reply);
in.setVersion(QDataStream::Qt_5_14);
connect(reply, &QNetworkReply::readyRead, [&]() {
    buffer.append(reply->readAll());
    if (buffer.size() >= L2) {
        // 处理完整的数据包
        processData(buffer.left(L2));
        buffer.remove(0, L2);
    }
});

// 处理错误信号
connect(reply, &QNetworkReply::errorOccurred, [](QNetworkReply::NetworkError error) {
    qDebug() << "Network error: " << error;
});

// 处理完成信号
connect(reply, &QNetworkReply::finished, []() {
    qDebug() << "Request finished.";
});