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. QTcpSocket how to receive different type of serialized objects in sequential ?
Forum Updated to NodeBB v4.3 + New Features

QTcpSocket how to receive different type of serialized objects in sequential ?

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 2.1k 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.
  • S Offline
    S Offline
    SpartaWHY117
    wrote on 18 Sept 2016, 17:15 last edited by A Former User
    #1

    current problem

    I write a class inherit form qtcpserver .this server will handle many clients , I override the method incommingConnection . if there comes new client , i will start a thread to handle it .

    but each client connect to server will send a config object first , so the server will receive the serialized config object first ,then return some info to client .then client will send serialized realtime infor object to server periodically . in every thread has a pointer to qtcpsocket ,connect it toreadyread function

    My question is how should i do in readyread function that i can get the qdatastream into property serialized object ?because first receive is config object , then comes the periodically realtime info object .

    1 Reply Last reply
    0
    • K Offline
      K Offline
      koahnig
      wrote on 18 Sept 2016, 18:16 last edited by
      #2

      Think of a QTcpClient as of a binary file. Whatever you have to write to a binary file in order to read it properly later on is also required here.

      There are many ways to do this. Most popular is to send before a short record or sequence of bytes to identify what comes next.

      Vote the answer(s) that helped you to solve your issue(s)

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SpartaWHY117
        wrote on 19 Sept 2016, 04:58 last edited by
        #3

        thanks for your answer ,but i don't get your point . As you say send some sequence bytes to identify what come next ,so what is the property way to do in that function ?

        //connect function 
        connect(tcpSocket, &QIODevice::readyRead, this, &FortuneThread::getInfo);
        
        //get info
        void FortuneThread::getInfo()
        {
        		in.startTransaction();
                        
                         //what should i do here to judge what serialized object come in ?
        		//if some sequential bytes to identify ,like string 
                        //just like the flowing code ?
                        in>>identifyString ;
                        switch(identifyString )
                                {
                                       //some handle 
                                  }
                         //but how to handle if comes in is serialized object ?
                        
        		if (!in.commitTransaction())
        			return;		
        
        }
        
        1 Reply Last reply
        0
        • V Offline
          V Offline
          VRonin
          wrote on 19 Sept 2016, 07:02 last edited by
          #4

          The more involved way is to treat the server as a state machine (http://doc.qt.io/qt-5/statemachine-api.html) so it changes state after it receives the config and is ready to recieve other data.

          The more dirty way is to define an enum with the type of transmission and append it at the beginning of the message.

          For example:

          enum TransmissionType :qint32 {
          sendingConfig = 8 // (a random number, I like 8, leave 0 for errors or special cases)
          , sendingRealtimeInfo
          }
          

          then every client before sending the actual data sends out one of those enum values (as a 32bit integer) so that when the server receives some data, it first reads this number to decide what kind of data it should read

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          S 1 Reply Last reply 20 Sept 2016, 18:13
          2
          • V VRonin
            19 Sept 2016, 07:02

            The more involved way is to treat the server as a state machine (http://doc.qt.io/qt-5/statemachine-api.html) so it changes state after it receives the config and is ready to recieve other data.

            The more dirty way is to define an enum with the type of transmission and append it at the beginning of the message.

            For example:

            enum TransmissionType :qint32 {
            sendingConfig = 8 // (a random number, I like 8, leave 0 for errors or special cases)
            , sendingRealtimeInfo
            }
            

            then every client before sending the actual data sends out one of those enum values (as a 32bit integer) so that when the server receives some data, it first reads this number to decide what kind of data it should read

            S Offline
            S Offline
            SpartaWHY117
            wrote on 20 Sept 2016, 18:13 last edited by
            #5

            @VRonin
            your answer is really helpful . but i still have not fully got your point .you say send the enum values , it's include realtimeInfo object in it ?

            if send enum value first ,then comes the serialized object ,so how to determine its enum or object ?

            void FortuneThread::getInfo()
            {
            		in.startTransaction();
                            
                           //do like this ?
                            in>>enmu_value ;
                           switch (enmu_value) 
                              {
                                     in>>object;
                              }
                           
            		if (!in.commitTransaction())
            			return;		
            }
            
            1 Reply Last reply
            0
            • V Offline
              V Offline
              VRonin
              wrote on 20 Sept 2016, 18:48 last edited by VRonin
              #6

              Untested code!!!

              [I do not use transaction but the old data size header, you should use transactions]

              sender (assume client)

              void Client::sendConfig(const ConfigClass& val)
              {
                  QByteArray block;
                  QDataStream out(&block, QIODevice::WriteOnly);
                  out
                      << static_cast<qint32>(0) //you can skip this if you use transactions
                      << static_cast<qint32>(TransmissionType::sendingConfig)
                      << val
                      ;
                  out.device()->seek(0); //you can skip this if you use transactions
                  out << static_cast<qint32>(block.size() - sizeof(qint32)); //you can skip this if you use transactions
                  m_tcpSocket->write(block);
              }
              
              void Client::sendRealtimeInfo(const RealtimeInfo& val)
              {
                  QByteArray block;
                  QDataStream out(&block, QIODevice::WriteOnly);
                  out
                      << static_cast<qint32>(0) //you can skip this if you use transactions
                      << static_cast<qint32>(TransmissionType::sendingRealtimeInfo)
                      << val
                      ;
                  out.device()->seek(0); //you can skip this if you use transactions 
                  out << static_cast<qint32>(block.size() - sizeof(qint32)); //you can skip this if you use transactions
                  m_tcpSocket->write(block);
              }
              

              receiver (assume server)

              // qint32 m_nextBlockSize;
              // connect(m_tcpSocket, &QTcpSocket::readyRead, this, &Server::ReadTransmission);
              void Server::ReadTransmission()
              {
                  QDataStream incom(m_tcpSocket);
                  qint32 RequestType;
                  for (;;) {
                      //from here
                      if (m_nextBlockSize == 0) {
                          if (m_tcpSocket->bytesAvailable() < sizeof(qint32))
                              break;
                          incom >> m_nextBlockSize;
                      }
                      if (m_tcpSocket->bytesAvailable() < m_nextBlockSize)
                          break;
                      //to here can be replaced using transactions
                      incom >> RequestType;
                      switch (RequestType) {
                      case TransmissionType::sendingConfig:{
                          ConfigClass val;
                          incom >> val;
                          // do something with the config
                      }
                                                           break;
                      case TransmissionType::sendingRealtimeInfo:{
                          RealtimeInfo val;
                          incom >> val;
                          // do something with the realtime info
                      }
                                                                 break;
                      }
                      m_nextBlockSize = 0;
                  }
              }
              

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              S 1 Reply Last reply 20 Sept 2016, 19:11
              2
              • V VRonin
                20 Sept 2016, 18:48

                Untested code!!!

                [I do not use transaction but the old data size header, you should use transactions]

                sender (assume client)

                void Client::sendConfig(const ConfigClass& val)
                {
                    QByteArray block;
                    QDataStream out(&block, QIODevice::WriteOnly);
                    out
                        << static_cast<qint32>(0) //you can skip this if you use transactions
                        << static_cast<qint32>(TransmissionType::sendingConfig)
                        << val
                        ;
                    out.device()->seek(0); //you can skip this if you use transactions
                    out << static_cast<qint32>(block.size() - sizeof(qint32)); //you can skip this if you use transactions
                    m_tcpSocket->write(block);
                }
                
                void Client::sendRealtimeInfo(const RealtimeInfo& val)
                {
                    QByteArray block;
                    QDataStream out(&block, QIODevice::WriteOnly);
                    out
                        << static_cast<qint32>(0) //you can skip this if you use transactions
                        << static_cast<qint32>(TransmissionType::sendingRealtimeInfo)
                        << val
                        ;
                    out.device()->seek(0); //you can skip this if you use transactions 
                    out << static_cast<qint32>(block.size() - sizeof(qint32)); //you can skip this if you use transactions
                    m_tcpSocket->write(block);
                }
                

                receiver (assume server)

                // qint32 m_nextBlockSize;
                // connect(m_tcpSocket, &QTcpSocket::readyRead, this, &Server::ReadTransmission);
                void Server::ReadTransmission()
                {
                    QDataStream incom(m_tcpSocket);
                    qint32 RequestType;
                    for (;;) {
                        //from here
                        if (m_nextBlockSize == 0) {
                            if (m_tcpSocket->bytesAvailable() < sizeof(qint32))
                                break;
                            incom >> m_nextBlockSize;
                        }
                        if (m_tcpSocket->bytesAvailable() < m_nextBlockSize)
                            break;
                        //to here can be replaced using transactions
                        incom >> RequestType;
                        switch (RequestType) {
                        case TransmissionType::sendingConfig:{
                            ConfigClass val;
                            incom >> val;
                            // do something with the config
                        }
                                                             break;
                        case TransmissionType::sendingRealtimeInfo:{
                            RealtimeInfo val;
                            incom >> val;
                            // do something with the realtime info
                        }
                                                                   break;
                        }
                        m_nextBlockSize = 0;
                    }
                }
                
                S Offline
                S Offline
                SpartaWHY117
                wrote on 20 Sept 2016, 19:11 last edited by
                #7

                @VRonin
                thanks very much , now i have now your idea .Use a qint32 value as enum value ,put it in qdatastream first ,then put needed data in the same qdatastream .

                i almost forget that one stream can read in more than one type value .thank your very much again .

                1 Reply Last reply
                0

                1/7

                18 Sept 2016, 17:15

                • Login

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