QTCPSocket. Receiving corrupted QImage on server part
-
I have a client-server architecture the client send the a Video stream to the server part, if the frames size is not big than the frame is being sent ok, but if the frame is quite big (not sure about the sizes) than on the server side it's being corrupted, the lower part of the image is grey. I googled found that it's better to use QDataStream, but now the data can't be written into the socket. I get this error:
QIODevice::write (QBuffer): ReadOnly device - the problem is that I don't use QBuffer so I don't understand why this error is rising;
Code (Client):void _Camera::bytesWrittenC(qint64 b){ qDebug()<<"Data is ready:"<<b; } void _Camera::ReadyReadC(){ qDebug()<<"Ready read"; } void _Camera::SendData(QImage &frame){ QByteArray buffer; QDataStream out(buffer); out<<int(0); out<<frame; out.device()->seek(0); out<<buffer.size(); // QBuffer buffer(&ba); //buffer.open(QIODevice::ReadWrite); //frame.save(&buffer, "JPEG"); //ba.append("We did it"); //socket.setOpenMode(QIODevice::ReadWrite); if(connectedToHostC == false){ socket.connectToHost(QHostAddress::LocalHost,PORT,QIODevice::ReadWrite); connect(&socket,SIGNAL(readyRead()),this,SLOT(ReadyReadC())); connectedToHostC = true; } if(socket.isValid()){ qDebug()<<"Socket is valid"; } //socket.open(QIODevice::ReadWrite); if(socket.write(buffer)< buffer.size()){ qWarning("Transmit error"); } qDebug()<<"Bytes written"<<socket.waitForBytesWritten(2000); qDebug()<<"Bytes available"<<socket.bytesAvailable(); }
Server side code:
TCPSocket::TCPSocket() { socket = new QTcpSocket; connect(&server,SIGNAL(newConnection()),this,SLOT(newConnectionS())); } void TCPSocket::ListenS(){ if(server.listen(QHostAddress::LocalHost,PORT)){ qDebug()<<"Server is listening"; } else{ qDebug()<<"Server cannot be started"<<server.errorString(); } } void TCPSocket::newConnectionS(){ qDebug()<<"Connected"; //socket->open(QIODevice::ReadWrite); socket = server.nextPendingConnection(); connect(socket,SIGNAL(readyRead()),this,SLOT(newImageReceived())); if(socket->isOpen()){ qDebug()<<"Socket is open"; }else {qDebug()<<"Socket cannot be opened"<<socket->errorString();} } void TCPSocket::newImageReceived() { qDebug()<<"Img rece"; QByteArray ba; if(socket->bytesAvailable() <=0){ qDebug()<<"Cannot read from socket"<<socket->errorString(); }else{ while(socket->bytesAvailable()>0){ qDebug()<<"Server:"<<socket->bytesAvailable(); ba += socket->readAll(); } } QImage img = QImage::fromData(ba); socket->waitForReadyRead(2000); if(!img.isNull()){ if(checkFrame(img)){ //socket->write("1"); qDebug()<<"Frame ok"; }else{ qDebug()<<"Frame not ok"; //socket->write("0"); } emit sendImage(img); } }
-
If I understand your code correctly, you are writing the size of the image into the buffer and afterwards the image. Then you are sending the whole buffer via tcp.
On the receiving side you are not reading the size values. Therefore they should be now in the image as well. This cannot work. You need to read the size int first. This gives you also the number of bytes to expect. At the moment it is not even ensured that you have received all bytes.
-
@koahnig At the moment I want to finish the client side and after the server part. On the client side the data is not being written into the socket because of this error:
QIODevice::write (QBuffer): ReadOnly device
And I don't understand why this error is being raised, what device it want to be open so I could write data.
Or maybe you can help to fix the problem with the corrupted image? -
In here:
void _Camera::SendData(QImage &frame) { QByteArray buffer; QDataStream out(buffer); out<<int(0); out<<frame; out.device()->seek(0); out<<buffer.size();
you are using this constructor
The documentation says:
QDataStream::QDataStream(const QByteArray &a)
Constructs a read-only data stream that operates on byte array a. Use QDataStream(QByteArray, int) if you want to write to a byte array.*
Since QByteArray is not a QIODevice subclass, internally a QBuffer is created to wrap the byte array.and you are trying to write to it. The constructor above is mopre appropriate, because you can choose the openMode.
-
The combination, as you use, seems to be perfect from my perspective (corrected for openMode of ocurse). QDataStream provides you the i/o-operators, which are not available with QByteArray.
Note: I am not a fan of either class. I never used QDataStream and only rarely QByteArray. Typically, I am going for the STL versions there.