如何在QT中通过套接字传输较大的对象?

时间:2011-05-09 16:31:45

标签: c++ qt sockets

我想在客户端服务器程序中发送/接收图像文件和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,因此数据大小是可变的,有时在开始读取之前文件的末尾不会写入缓冲区。

有一个简单的解决方案吗?

3 个答案:

答案 0 :(得分:3)

我会首先发送一个固定大小的头,描述发送的数据,特别是字节的类型和大小。

然后,当您收到readReady事件时,您将可用的任何数据提取到缓冲区中。一旦确定已收到所有必要数据,就可以将其流式传输到QImage对象中。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

代码示例:

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长度,这样你就知道流出完整的QByteArray需要多大socket->bytesAvailable()。然后:

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