Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to wait for Qtcpsocket data without freezing the GUI?



  • I have implemented a **QTcpserver ** .After succesfull connection with the client( PLC), both exchange data in a 2 way hand shake.Means Server sends the data with a counter value and client will reply with the same value,the moment server receives the value it send with incremented counter value.This goes on in a loop. I have done using signals and slot.
    connect(m_tcpSocket, SIGNAL(readyRead()),this, SLOT(socketReadyRead()));
    In the slot of socketReadyRead(), I am emitting the signal to another slot where i send new data with incremented counter value.

     void TCPCommunicationPort::socketReadyRead()
    {
        emit newRawData();//connect to another slot where i send data
    //    qDebug()<<"bytes available "<<m_tcpSocket->bytesAvailable();
        QByteArray receivedData = m_tcpSocket->readAll();
    //I am updating the GUI written in QML though signals  
        emit sendDatatoQml(byteIndex,-1,overrideValue);
       ....
    }
    

    Now, I send 48Bytes of data and I receive **68 bytes **of data from the client. To perform a function called Homing. I need to set/enable particlular bits in 48Bytes of sendData(say bits 1 and 2 of 6th byte ) and wait till particular bit in 68 bytes (Recevied data)(say 3rd bit of 10th byte) is true(this will be after few seconds) and then I have disable the bits 1 and 2 of 6th byte .Meanwhile the server has to keep on sending 48 bytes of data with incremented counter value, otherwise it will disconnect. How to perfome this waiting ? note that already data is exchanging in a loop.
    I tried like this but Qt creator and app both freezed and crashed because of infinet while loop.

    void TCPCommunicationPort::startHoming()
    {
        if(!(m_senddataBuffer[CREG1] & (1 << EMSTOP)))
        {
            m_senddataBuffer[CREG1] |= 1<<EMSTOP;
            bool bitvalue = (m_senddataBuffer[CREG1] & (1 << EMSTOP));
            dataFromCppUpdate(CREG1,EMSTOP,bitvalue);
        }
        if(!(m_senddataBuffer[CREG1] & (1 << MSTOP)))
        {
            m_senddataBuffer[CREG1] |= 1<<MSTOP;
            bool bitvalue = (m_senddataBuffer[CREG1] & (1 << MSTOP));
            dataFromCppUpdate(CREG1,MSTOP,bitvalue);
        }
        //    emit newRawData();
        bool enter =true;
        while(enter) {
            qDebug()<<"I am waiting..";
            if(m_tcpSocket->waitForReadyRead())
            {
             bool bitValue =(receivedData[byteIndex] & (1 << bitIndex));//I am reading the socketReadyRead in SocketReadyready SLOT.
             If(bitValue)
            {
             //disable the bit.
             }
                break;
            }
        }
        qDebug()<<"homing is done";
    }
    

    Can any one please tell me the logic to wait without freezing the GUI.Do i need to put this function startHoming in separate Qthread ? If so how to do that? Please provide me an example.Thanks a lot


  • Lifetime Qt Champion

    Hi,

    waitForReadyRead already does the blocking part but plays nicely with the event loop. Remove your while loop



  • @SGaist
    Okay,I removed the while loop.I don't know why the debug() statement qDebug()<<"I am waiting.." is never called.That means I am not entering into the If statement if(m_tcpSocket->waitForReadyRead())please note that data sending SLOT connect(this,SIGNAL(newRawData()),this,SLOT(sendRawData()));is called almost every 30ms, otherwise client will be disconnected.That means already kinda loop is running.Will the program waits at this point if(m_tcpSocket->waitForReadyRead())?

    void TCPCommunicationPort::startHoming()
    {
        qDebug()<<"TCPCommunicationPort::startHoming";
        if(!(m_senddataBuffer[CREG1] & (1 << EMSTOP)))
        {
            m_senddataBuffer[CREG1] |= 1<<EMSTOP;//set the Bit to true
            bool bitvalue = (m_senddataBuffer[CREG1] & (1 << EMSTOP));
            dataFromCppUpdate(CREG1,EMSTOP,bitvalue);
        }
        if(!(m_senddataBuffer[CREG1] & (1 << MSTOP)))
        {
            m_senddataBuffer[CREG1] |= 1<<MSTOP;
            bool bitvalue = (m_senddataBuffer[CREG1] & (1 << MSTOP));
            dataFromCppUpdate(CREG1,MSTOP,bitvalue);
        }
        //    emit newRawData();
    
        if(m_tcpSocket->waitForReadyRead())
        {
            qDebug()<<"I am waiting..";
        }
    
        qDebug()<<"homing is done";
    }
    

  • Lifetime Qt Champion

    It means that there was nothing to read until the timeout of waitForReadyRead



  • @SGaist (
    Now It works but I think my explanation is wrong. Let me tell you once again. I am getting data from client almost every 30ms and I am reading it to receivedData[] . That means connect(m_tcpSocket, SIGNAL(readyRead()),this, SLOT(socketReadyRead())); socketReadyRead() is called every 30ms. So my IF statement works.But I must wait till one of the Bit in 68Bytes(say 3rd bit of 10th byte ) of data i receive from client is enabled.It keeps on sending 68 bytes of data(every 30ms) but after some time when the work is done it will send me an Ack (Almost after 10 Sec(i.e 10000ms)) by enabling the 3rd bit(ACKSTART) of 10th byte(SREG1).How should i wait there till that bit is enabled?

    if(m_tcpSocket->waitForReadyRead())
        {
            qDebug()<<"I am waiting for ACK...";
    
            if((m_oldData[SREG1] & (1 << ACKSTART)))//how should I wait here till that bit is enabled?
            {
                qDebug()<<"Ack received";
            }
        }
        qDebug()<<"homing is done";
    

  • Lifetime Qt Champion

    Don't put any infinite loop because you are waiting for the ACK. Just use a signal to tell your program to continue when you actually received it.

    You should maybe consider using a state machine to model that



  • @SGaist
    Thanks for the hint. your are right It's like a state machine model .I am using switch case statements. Waiting in a case till that is true and then moving to another state. But it seems to be lot of switch cases and lot of condition check variables. Is there any good practise instead of switch case and if else statements? Thanks


  • Lifetime Qt Champion

    Well, the Qt State Machine Framework looks like a good place to start


Log in to reply