【问题标题】:How to transfer larger objects through a socket in QT?如何通过 QT 中的套接字传输较大的对象?
【发布时间】:2014-02-05 01:05:27
【问题描述】:

我想在客户端服务器程序中发送/接收图像文件和 2 个整数作为消息。

我为此使用QLocalSocketQImage

但是我不知道如何仅在图像和整数完全写入缓冲区后从套接字读取,因为readyRead 信号已经在前几个字节后触发。

这是我的部分代码:

// sending
QDataStream stream(socket);
stream << image << i << j;


// recieving
void MainWindow::readyRead() {
    // ...
    if (socket->bytesAvailable() > 400)
    {
        QByteArray b = socket->readAll();
        QDataStream stream(&b, QIODevice::ReadOnly);

        QImage image;
        int i, j;
        stream >> image >> i >> j;
    // ...
    }
}

我尝试猜测传入的文件大小,但由于 QImage 被序列化为 PNG,因此数据大小是可变的,有时文件末尾在我开始读取之前不会写入缓冲区。

有没有简单的解决方案?

【问题讨论】:

  • 能不能先发图片的大小?例如,在由公共接口定义的标头结构中。您还可以包含其他有用的信息,例如发件人标签、时间戳、姓名等...

标签: c++ qt sockets


【解决方案1】:

我会先发送一个固定大小的标头来描述正在发送的数据,特别是类型和大小(以字节为单位)。

然后,当您接收到 readReady 事件时,您会将任何可用数据拉入缓冲区。一旦你确定你已经收到了所有必要的数据,你就可以将它流式传输到一个 QImage 对象中。

【讨论】:

    【解决方案2】:

    BMP 格式具有大小信息,PNG 格式具有每个块的大小信息。这些是 QImage 序列化的格式。

    如果您不想从原始数据中提取信息,请先将 QImage 序列化为 QBuffer(这样您就可以更好地了解/控制大小和格式)。然后流式传输该大小和缓冲区。

    【讨论】:

    • 谢谢,我设法从 QBuffer 中获取了对象的大小,现在可以使用了。
    【解决方案3】:

    代码示例:

    QBuffer buffer;
    image.save(&buffer, "PNG", 100); //can change the compression level to suit the application - see http://qt-project.org/doc/qt-4.8/qimage.html#save
    qint64 length = sizeof(quint32) + buffer.data().size(); //http://doc.qt.digia.com/4.7/datastreamformat.html
    stream << length;
    stream << buffer.data();
    

    然后在另一端,首先输出 qint64 长度,这样您就知道socket-&gt;bytesAvailable() 必须有多大才能输出完整的 QByteArray。那么:

    QByteArray ba;
    stream >> ba;
    QImage image = QImage::fromData(ba); // Get image from buffer data
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      • 1970-01-01
      相关资源
      最近更新 更多