3

我正在将 .jpg 图像从 Qt 客户端发送到 python 服务器。Qt 客户端发送如下:

void Sender::sendToServer(QByteArray imageData)
{
    QDataStream stream(serverSocket);
    int t = imageData.size();
    stream << t;
    stream << imageData;
    serverSocket->waitForBytesWritten(-1);
    qDebug() << "Frame size:" << imageData.size();
}

服务器是:

unpacker = struct.Struct('!i')
conn, addr = s.accept()
bool = True
data = b''
while True:
    while len(data) < 4:
        try:
            data += conn.recv(100)
        except:
            break
    img_size = unpacker.unpack(data[:4])[0]
    print('size: ', img_size)
    print('Data: ',data)
    print('Image: ',data[:8])  # deleting preceding 8 bytes
    # image processing

输出是:

//Client:
Frame size: 49993

//Server:
size: 49993
Data: b'\x00\x00\xc3\r\x00\x00\xc3\r\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01...
Image: b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00...

在输出中,.jpg 文件从'\xff\xd8'开始。由于 C++ int是 4 字节,服务器需要“ {4 byte}\xff\xd8... ”。但是,前面的字节总是不同的大小。有时是 8 个字节,但有时甚至不同(例如 6 或 9 个字节)。我无法弄清楚它背后的原因。这里有什么问题?

平台:win7、Qt 5.9.1、Python 3.4。


编辑

按照@Frank的回答,我将代码更改如下,一切正常:

Qt客户端发送方法:

void Sender::sendToServer(QByteArray imageData)
{
    QDataStream stream(serverSocket);
    QString size = QString::number(data.size());
    QString size_8_byte = size.rightJustified(8, ' ');  // add spaces to make it exactly 8 bytes
    imageData.prepend(size_8_byte.toUtf8());
    stream.writeRawData((char*)(imageData.data()), imageData.size());

    serverSocket->waitForBytesWritten(-1);
}

Python服务器:

unpacker = struct.Struct('8s')
conn, addr = s.accept()
data = b''
bool = True
while True:
    while len(data) < 8:
        try:
            data += conn.recv(100)
        except:
            break
    img_size = unpacker.unpack(data[:8])[0]
    img_size = int(img_size.decode("utf-8").strip())  #remove spaces and convert to int
    data = data[8:]     #correct data
    #image processing
4

1 回答 1

2

QDataStream不是一个简单的二进制转储程序,它以某种内部定义的方式格式化数据。这有助于解决字节序校正等问题,

但是,有一个非常简单的修复方法可供您使用:QDataStream提供writeRawData()绕过所有格式化操作的函数。

只需将您的输出操作更改为使用它,您就可以开始使用了。

于 2018-01-04T05:09:13.480 回答