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);
        }
    
    }
    

  • Moderators

    @mandruk1331

    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?


  • Moderators

    @mandruk1331

    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.



  • @koahnig is it better to use QByteArray or QDataStream?


  • Moderators

    @mandruk1331

    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.



  • @koahnig In my project I use a combination of QBuffer and QByteArray but in the future I think to use QDataStream.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.