在Qt中读取套接字中的所有数据

时间:2014-11-26 18:36:27

标签: c++ qt sockets tcp

我正在尝试通过Qt中的网络套接字(TCP)发送图像。它适用于小图像(小于8192字节),但由于接收端不知道应该有多大(因此在尝试显示和图像之前不等待接收所有数据),因此无法处理较大的图像。

我尝试将数据大小添加到数组的开头并在另一端读取它,但是我在接收端得到的数字与发送前插入的数字不匹配。谁能看到我做错了什么?

void Screenshot_controller::serializeImage(std::string fileType, QImage imageToSerialize, QByteArray *imageStream)
{
    QBuffer imageBuffer(imageStream);
    const char * extention = fileType.c_str();
    imageToSerialize.save(&imageBuffer, extention);
    //QString dataType = "Img";
    //imageStream->insert(0, dataType);
    qint32 size = imageStream->size();
    imageStream->insert(0, size);
}

//Called using a signal when data is received on the socket
void Screenshot_controller::readyRead()
{
    qDebug() << "Client Reading...";
    QByteArray rxByteArray;
    rxByteArray = rxSocket->readAll();
    qint32 size = rxByteArray.at(0);    
    QImage imageToDisplay;
    deSerializeImage("BMP", &imageToDisplay, rxByteArray);
    displayImage(imageToDisplay);
}

2 个答案:

答案 0 :(得分:1)

没有方法QByteArray::insert(int,uint32);你的uint32将被转换为char,你最终得到QByteArray::insert(int,char);你可能会考虑使用

QByteArray(0,(const char *)&size,sizeof(uint32));

如果多个平台之间的结束不是问题。

答案 1 :(得分:1)

我相信你的问题是:

imageStream->insert(0, size);

如果查看QByteArray man page,您会看到可以将qint32作为其第二个参数的insert()方法的唯一实现是:

QByteArray & insert (int i, char ch);

...这意味着您在QByteArray的前面插入一个字节而不是四个字节。截断值:问题是单个字节不能容纳任何大于255的值,大多数图像的长度超过255个字节。

同样,在解码步骤中,你有这个:

qint32 size = rxByteArray.at(0);    

同样,at()方法返回一个字节,因此无论原始图像有多大,您的大小值都不会大于255。

对此的修复是插入4个字节(因为sizeof(qint32)== 4)代替大小值。像这样的东西会插入值(使用明确定义的endianness):

qint32 beSize = htonl(size);
imageStream->insert(0, (const char *) &beSize, sizeof(beSize));

......然后这样的事情可以再次提取它:

qint32 beSize = *((const qint32 *) rxByteArray.constData());
qint32 size = ntohl(beSize);