Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSslSocket::readyRead() signal is not raise after sending data ..
Forum Updated to NodeBB v4.3 + New Features

QSslSocket::readyRead() signal is not raise after sending data ..

Scheduled Pinned Locked Moved Solved General and Desktop
25 Posts 6 Posters 7.4k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Ritchie
    wrote on last edited by
    #13

    Thanks to all,

    I will update my program with your recommendations and come back
    with results.

    Best regards
    R.

    1 Reply Last reply
    0
    • R Offline
      R Offline
      Ritchie
      wrote on last edited by Ritchie
      #14

      Hi to all,
      @aha_1980
      I change the waiting function to

          if( m_sslSocket->bytesAvailable() < 6 )
              return;
      
      

      This works as well and will not block.
      Thanks for this info.

      Of course you may also be right that the event loop is not running at all. We'll see when we get more information.

      Is the event Loop for each thread or the complete system,
      because I have also run a front end and a second thread reading sensor values.

      PS: And make sure you don't call blockSignals() - this was the reason for a timer not calling it's slot some days ago in this forum.

      I do not use "blockSignals() " in my source code. Are there know functions of QT, which are using this function ?

      @J-Hilk

      I believe you delete your block before write is finished, write is asynchronus after all.

      Transmission to the server is working fine, since the connection is established.

      @JNBarchan
      waitForReadyRead(0) does not work.
      I check the value 5, which will work as the smallest value.
      But up to now, I am working locally and the server has to
      do a query in the database for the answer.
      See what happen later in real envirement (internet via mobil to the server).

      Your deleteLater is a nicer pattern.

      When I use deletelater, at which time will QT delete the object,
      because the function is call several times in a minute.

      Here is the complete code of the client

      //
      // C++ Implementation: Datathread
      //
      // Description: 
      //
      //
      // Author: 
      //
      // Copyright: See COPYING file that comes with this distribution
      //
      //
      #include			<QDebug>
      #include            <QSettings>
      #include			<QMessageBox>
      #include            <QThread>
      
      #include            "ProgramDiagnose.h"
      #include            "DataThread.h"
      
      extern			QString					ApplicationPath;        // Path of the exe File
      
      
      class           SensorValueData;
      
      // ************************************************************
      //				Constructor
      // ************************************************************
      
      DataThread::DataThread(int	*PPointer,SensorValueDatas *SensorBufferPointer, ProgrammDiagnosis    *DebugPointer)
      {
          m_ProgramIsRunning = PPointer;
          SensorQueryBuffer = SensorBufferPointer;
          ProgramInfo=DebugPointer;
          m_StateMachineState=NoConnection;
          loadSystemSettings();
      }
      
      // ************************************************************
      //			Destructor
      // ************************************************************
      DataThread::~DataThread()
      {
      }
      
      // **************************************************************************
      // Load the system settings of the thread
      // **************************************************************************
      void		DataThread::loadSystemSettings(void)
      {
      
          QSettings 				settings(ApplicationPath + "../config/carinfo.ini",QSettings::IniFormat);
      
          settings.beginGroup("DataServer");
          m_ServerTCPIPAddress	=settings.value("IP", "localhost").toString();		// Car Server Name
          m_ServerTCPIPPort		=settings.value("Port", "localhost").toInt();       // Name of the SQL Database;
          m_LocalSSLCertificate    =settings.value("SSLCertificate", "sslserver.pem").toString();         //
          settings.endGroup();
      
          settings.beginGroup("CustomerInfo");
          m_CustomerID            =settings.value("CustomerID", "-").toInt();      // Customer ID
          m_SerialNumber          =settings.value("SerialNo", "-").toString();
          m_CarType               =settings.value("CarType", "-").toString();
          settings.endGroup();
      }
      
      // ************************************************************
      //          Send out a record data set
      // ************************************************************
      void  DataThread::sendRecordData(void)
      {
      QByteArray					*block;										// Stream Buffer
      SensorValueData             *TempValue;
      
          m_blockSize=0;                                                      // clear the record size value
          m_NumberOfBytesSend=0;                                              // Clear the number of byte send
          TempValue = SensorQueryBuffer->getIndex(0);
          block	= new QByteArray;                                   		// create Stream Buffer
          m_Command.clear();
          m_ParameterType=RecordData;
          m_Command.addParameter((int)m_ParameterType);
          m_Command.setCommand(TCPIP_CMD_REQUEST_DATA);                        // data will be send to the server
      
          QDataStream			outStream(block, QIODevice::ReadWrite);         // just for write only
          outStream.setVersion(QDataStream::Qt_5_4);							// Set the version of stream
          outStream << (m_blockSize);											// Reserve memory for size
          outStream << m_Command ;											// Setup the command
          outStream << *TempValue;                                            // send out the Data
          outStream.device()->seek(0);										// jump back to the start of the block
          m_blockSize = (quint64)block->size();
          outStream << m_blockSize;                                           // write the size of data - size info into
          m_sslSocket->write(*block);											// Send data to the Server
          m_sslSocket->flush();                                               // send out the data to the server now
          m_StateMachineState=CommandSend;                                    //
          m_sslSocket->waitForReadyRead(5);
          delete  block;
      }
      
      // ************************************************************
      //				Run function of the thread
      // ************************************************************
      void DataThread::doWork(void)
      {
          ProgramInfo->writelog(QObject::tr("carclient"),QObject::tr("DataThread"),QObject::tr("Info"),QObject::tr("Thread startup"));
      
          m_sslSocket=new QSslSocket(this);
      
          connect(m_sslSocket,SIGNAL(disconnected(void)), this,SLOT(disconnected(void)));
          connect(m_sslSocket,SIGNAL(encrypted(void)), this, SLOT(SSLReady(void)));
      
          typedef void (QSslSocket::* sslErrorsSignal)(const QList<QSslError> &);
          connect(m_sslSocket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors),this, &DataThread::SSLError);
      
          connect(m_sslSocket,SIGNAL(readyRead(void)), this,SLOT(SocketReadyRead(void)));
          connect(m_sslSocket,SIGNAL(aboutToClose(void)), this,SLOT(aboutToClose(void)));
      //    connect(m_sslSocket,SIGNAL(bytesWritten(qint64)), this,SLOT(bytesWritten(qint64)));
      
          m_sslSocket->addCaCertificates(ApplicationPath + "../config/" + m_LocalSSLCertificate);
          if (! QSslSocket::supportsSsl())
              {
              ProgramInfo->writelog(QObject::tr("carclient"),QObject::tr("DataThread"),QObject::tr("Failure"),QObject::tr("No support fpr SSL connection!"));
              }
          QThread::msleep(4000);														// Wait a little bit
      //    m_sslSocket->ignoreSslErrors();
      
          while( *m_ProgramIsRunning == true )								// wait until program is close down
      		{
              if( SensorQueryBuffer->Size() > 0 )
                  {
                  if ( ! SensorQueryBuffer->locked() )
                      {
                      if (m_sslSocket->state() != QTcpSocket::ConnectedState)
                          {
                          if( m_StateMachineState == NoConnection )
                              {
                              m_StateMachineState=TryToConnect;
                              m_sslSocket->connectToHostEncrypted(m_ServerTCPIPAddress, m_ServerTCPIPPort);
                              m_sslSocket->waitForEncrypted(-1);
                              }
                          }
                      }
                  }
      		}
      
         if( m_StateMachineState != NoConnection )
          {
          m_sslSocket->close();
          m_sslSocket->disconnectFromHost();
          }
          emit    WorkFinished();
      }
      
      // ************************************************************
      //          Connection was disconnected
      // ************************************************************
      void    DataThread::disconnected(void)
      {
          SensorQueryBuffer->clearLock();                     // release lock of the data
          m_StateMachineState=NoConnection;                   // State to disconnected
      }
      
      // ************************************************************
      //          Host is found from Client
      // ************************************************************
      void    DataThread::hostFound(void)
      {
      }
      
      // ************************************************************
      //              SSL Connection established
      // ************************************************************
      void    DataThread::SSLReady(void)
      {
          if( m_StateMachineState !=CommandSend )
              {
              m_StateMachineState=SocketConnected;
              SensorQueryBuffer->setLocked();
              sendRecordData();                                      // Send out the data
              }
      }
      
      // ************************************************************
      //      We get a new connection. Send out the command
      // ************************************************************
      void    DataThread::connected(void)
      {
      }
      
      // ************************************************************
      //      There was a error inbetween the transmission
      // ************************************************************
      void    DataThread::SSLError(const QList<QSslError> errors)
      {
          m_LastErrorMessage=m_sslSocket->errorString();
      //    m_sslSocket->ignoreSslErrors( );
          SensorQueryBuffer->clearLock();
          m_sslSocket->disconnectFromHost();
          m_StateMachineState=NoConnection;                   // State to disconnected
          m_sslSocket->close();
      
          ProgramInfo->writelog(tr("carclient"),
                                tr("DataThread"),
                               tr("Error on Connection %3"),
                               tr("Data Background Abort 1 Function (%1::%2)!").arg(m_ServerTCPIPAddress).arg(m_ServerTCPIPPort).arg(m_LastErrorMessage));
      
      //    emit showMessageFromThread(tr("Critical System Error"),
      //                            tr("DataThread (%1::%2)!").arg(m_ServerTCPIPAddress).arg(m_ServerTCPIPPort),
      //                            tr("Error %1 on Connection !").arg(m_LastErrorMessage),
      //                           (int)QMessageBox::Critical );
      }
      
      // ************************************************************
      //      Client receiveds byte from Server
      // ************************************************************
      void    DataThread::SocketReadyRead(void)
      {
      QByteArray block;
      
      
          if( m_sslSocket->bytesAvailable() < 6 )
              return;
      
          QDataStream inStream(m_sslSocket);                 // Create a data stream by tcp/ip
          inStream.setVersion(QDataStream::Qt_5_4);           // we are using version .. for Transmission
      
          inStream >> block;
      
          QString sAnswer(block.data());
      
          switch(m_ParameterType)
              {
              case    NoParameter:
                      break;
              case    RecordData:
                      if(sAnswer == "OK")
                          {
                          SensorQueryBuffer->remove(0);      // remove value only if transmitted
                          }
                      SensorQueryBuffer->clearLock();        // release lock of the data
                      break;
              case    CustomerData:
                      break;
              case    LastPosition:
                      break;
              }
      
      
           m_sslSocket->disconnectFromHost();
           m_sslSocket->close();
           m_StateMachineState=NoConnection;
      }
      
      // ************************************************************
      //          Connection is about to close
      // ************************************************************
      void    DataThread::aboutToClose(void)
      {
          m_StateMachineState=NoConnection;                   // State to disconnected
          SensorQueryBuffer->clearLock();                     // release lock of the data
      }
      
      // ************************************************************
      // Do we have send out all datas to the server
      // ************************************************************
      void    DataThread::bytesWritten(qint64 NumberOfBytes)
      {
          m_NumberOfBytesSend += NumberOfBytes;
          if(m_NumberOfBytesSend == m_blockSize)
              {
              switch(m_ParameterType)
                  {
                  case    NoParameter:
                          break;
                  case    RecordData:
                          break;
                  case    CustomerData:
                          break;
                  case    LastPosition:
                          break;
                  }
              }
      }
      

      Best regards
      R.

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #15

        Hi,

        Out of curiosity, why allocate block on the heap ? Since you delete it anyway at the end of the function, just allocate it on the stack. You'll avoid all the troubles you had with deleting it by hand before it was completely sent.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • aha_1980A Offline
          aha_1980A Offline
          aha_1980
          Lifetime Qt Champion
          wrote on last edited by
          #16

          @Ritchie:
          I just saw from your last code that you also have m_sslSocket->waitForEncrypted(-1);. In principle, I would avoid mixing the waitForXxx() functions with the signal-slot mechanism.

          I also just recognized, that your code runs within a thread, correct? Using blocking functions is totally valid in threads, but as said above, I'd not mix this with signals-slots.

          Further, a thread does not use the event loop of your main program. If you want to use slots in your thread, than you need to implement an event loop for it. Emitting signals from within you thread (e.g. to the main thread) is always possible, but using slots within your thread needs an separate event loop.

          And maybe this is already the problem why your slot is only called when you have the waitForReadyRead() function active?

          Qt has to stay free or it will die.

          1 Reply Last reply
          0
          • R Offline
            R Offline
            Ritchie
            wrote on last edited by
            #17

            @aha_1980
            But when I remove the line

            m_sslSocket->waitForEncrypted(-1);
            

            the complete communication will not established.

            This was posted here:
            https://forum.qt.io/topic/84370/create-a-ssl-connection-only-with-slots-and-signals

            There is also a sample program posted (download because of to big files).

            I do not get the "encrypted()" signals in this case and I do not know, why.
            But with the "m_sslSocket->waitForEncrypted(-1);" I got the signal.

            Best regards
            R.

            1 Reply Last reply
            0
            • R Offline
              R Offline
              Ritchie
              wrote on last edited by
              #18

              Hi,

              I just reinstall the complete system to make sure that it is not my installation.
              But the problem is still existing.

              • The server program receives a request for a new connection and start a new instance of the SSLSocket.

              But after the command

              m_sslSocket->startServerEncryption();
              

              on the server nothing happens on the client. Still!

              But now I at a slot

                  connect(m_sslSocket,SIGNAL(connected(void)), this, SLOT(ConnectionEstablished(void)));
              

              and noticed, that when I close my frontend application which is working
              like the sample application of QML, here the start code of the window

                  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                  QGuiApplication app(argc, argv);
              
                  app.setOrganizationName(CLIENT_PROGRAM_NAME);
                  QTextCodec::setCodecForLocale( QTextCodec::codecForName("UTF-8") );
                  QLocale::setDefault(QLocale::German);
                  QQuickStyle::setStyle(QStringLiteral("qrc:/qml/Style"));
                  QQmlApplicationEngine engine;
                  engine.rootContext()->setContextProperty("BackEnd", &UserDisplay);
                  engine.load(QUrl(QStringLiteral("qrc:/client.qml")));
              

              i receive a "Connected" signal.

              That sounds for my, that my QML Application is blocking signals, which I do not know.

              Is it allow to have a front end, like the sample program and running a back ground program for communication ?

              Best regards
              R.

              aha_1980A 1 Reply Last reply
              0
              • R Ritchie

                Hi,

                I just reinstall the complete system to make sure that it is not my installation.
                But the problem is still existing.

                • The server program receives a request for a new connection and start a new instance of the SSLSocket.

                But after the command

                m_sslSocket->startServerEncryption();
                

                on the server nothing happens on the client. Still!

                But now I at a slot

                    connect(m_sslSocket,SIGNAL(connected(void)), this, SLOT(ConnectionEstablished(void)));
                

                and noticed, that when I close my frontend application which is working
                like the sample application of QML, here the start code of the window

                    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                    QGuiApplication app(argc, argv);
                
                    app.setOrganizationName(CLIENT_PROGRAM_NAME);
                    QTextCodec::setCodecForLocale( QTextCodec::codecForName("UTF-8") );
                    QLocale::setDefault(QLocale::German);
                    QQuickStyle::setStyle(QStringLiteral("qrc:/qml/Style"));
                    QQmlApplicationEngine engine;
                    engine.rootContext()->setContextProperty("BackEnd", &UserDisplay);
                    engine.load(QUrl(QStringLiteral("qrc:/client.qml")));
                

                i receive a "Connected" signal.

                That sounds for my, that my QML Application is blocking signals, which I do not know.

                Is it allow to have a front end, like the sample program and running a back ground program for communication ?

                Best regards
                R.

                aha_1980A Offline
                aha_1980A Offline
                aha_1980
                Lifetime Qt Champion
                wrote on last edited by aha_1980
                #19

                @Ritchie we already gave you some pointers.

                Again: don't mix waitForReadyXxxx() with signals&slots!

                If your complete program is not working, its often best to start from scratch with a minimal working example. then build your way to a full program. when you stuck, ask specific questions, we may then be able to help you. most often you can answer you question yourself already.

                Qt has to stay free or it will die.

                1 Reply Last reply
                2
                • R Offline
                  R Offline
                  Ritchie
                  wrote on last edited by
                  #20

                  Hi,

                  Again: don't mix waitForReadyXxxx() with signals&slots!

                  I do not use any "waitForReadyXxxx()" within my program.
                  I used once "m_sslSocket->waitForReadyRead(10);" to show, that suddenly a change was happen. But it solve not my problem.

                  Anyways I guess the main reason why it does not work it,
                  that I have to call "QThread:exec()" with the thread once to support signal and slots in the QThread.

                  But when I call "QThread:exec()" I will not execute any other code in the class.

                  But I would like to execute the loop which is coded in the function "void DataThread::doWork(void)"

                  How can I execute "void DataThread::doWork(void)" and let "Qthread:exec()" have at the same time ?

                  Best regards
                  R.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #21

                    You should take a look at the example provided in the QThread details documentation more specifically the one for the worker object implementation.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      Ritchie
                      wrote on last edited by
                      #22

                      Hi,

                      I am already using the first way, shown in the examples.

                      But the documents says:

                      A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

                      So, if I not execute the "Exec()" command, so far I understand, the QT Event Loop will not starts.

                      But within the examples, there is no using any "exec()".

                      It says for the first sample:

                      The code inside the Worker's slot would then execute in a separate thread. However, you are free to connect the Worker's slots to any signal, from any object, in any thread. It is safe to connect signals and slots across different threads, thanks to a mechanism called queued connections.

                      So in this case, no "exec()" is needed in the separate thread to execute ?

                      And for the second sample it says

                      In that example, the thread will exit after the run function has returned. There will not be any event loop running in the thread unless you call exec().

                      Best regards
                      R.

                      1 Reply Last reply
                      0
                      • Pablo J. RoginaP Offline
                        Pablo J. RoginaP Offline
                        Pablo J. Rogina
                        wrote on last edited by
                        #23

                        @Ritchie I'm assuming your "program" is a client connecting securely to a server, because you're using

                        m_sslSocket->write(*block);
                        m_sslSocket->flush(); 
                        

                        so I don't getting why you're expecting a readyRead() signal, since that will happen when you are reading data, not writing it. From Qt's documentation:

                        void QIODevice::readyRead()

                        This signal is emitted once every time new data is available for reading from the device's current read channel.

                        Am I missing something? If so my apologies right now...

                        Upvote the answer(s) that helped you solve the issue
                        Use "Topic Tools" button to mark your post as Solved
                        Add screenshots via postimage.org
                        Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

                        1 Reply Last reply
                        1
                        • R Offline
                          R Offline
                          Ritchie
                          wrote on last edited by
                          #24

                          @Pablo-J-Rogina
                          You are right, the

                          void QIODevice::readyRead()

                          is only emitted after receiving bytes from the server.
                          And after sending data's from the client to the server, the server will answer.

                          Like "Data stored" correct or "Data not stored"

                          Best regards
                          R.

                          1 Reply Last reply
                          0
                          • R Offline
                            R Offline
                            Ritchie
                            wrote on last edited by
                            #25

                            Hi to all,

                            I solved my problem by the following way.

                            The function "DoWork" was change in the follwing way. Now it calls the QThread::exec() function.
                            The loop function is done by a timer event.

                            void DataThread::doWork(void)
                            {
                                ProgramInfo->writelog(QObject::tr("carclient"),QObject::tr("DataThread"),QObject::tr("Info"),QObject::tr("Thread startup"));
                            
                                if (! m_sslSocket->supportsSsl())
                                    {
                                    ProgramInfo->writelog(QObject::tr("carclient"),QObject::tr("DataThread"),QObject::tr("Failure"),QObject::tr("No support fpr SSL connection!"));
                                    }
                            
                                m_WorkTimer = new QTimer();
                                connect(m_WorkTimer, SIGNAL(timeout()), this, SLOT(DoTimerWork()));
                                m_WorkTimer->start(50);
                            
                                QThread::exec();
                            
                                m_WorkTimer->stop();  // will delete later
                            
                               if( m_StateMachineState != NoConnection )
                                {
                                m_sslSocket->close();
                                m_sslSocket->disconnectFromHost();
                                }
                                emit    WorkFinished();
                            }
                            

                            Within the function "DoTimerWork", I do the cyclic stuff and do not block the events anymore

                            void    DataThread::DoTimerWork(void)
                            {
                                if( SensorQueryBuffer->Size() > 0 )
                                    {
                                    if ( ! SensorQueryBuffer->locked() )
                                        {
                                        if (m_sslSocket->state() != QTcpSocket::ConnectedState)
                                            {
                                            if( m_StateMachineState == NoConnection )
                                                {
                                                m_StateMachineState=TryToConnect;
                                                m_sslSocket->connectToHostEncrypted(m_ServerTCPIPAddress, m_ServerTCPIPPort);
                                                }
                                            }
                                        }
                                    }
                            }
                            
                            

                            Thanks to all try to help me.

                            Best regards
                            R.

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved