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. Two way comms via socket?

Two way comms via socket?

Scheduled Pinned Locked Moved Solved General and Desktop
28 Posts 4 Posters 1.5k Views
  • 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I have one process listening to any address on port 8123. The other process is sending a message to the first. The first process receives the message and sends a response on the same socket it receives the first message.

    On the process that is sending the message I am connecting to the following signals:

    QAbstractSocket::connected
    QAbstractSocket::readyRead
    QAbstractSocket::disconnected
    

    I can see the message is being received correctly by the first process, but instead of the response on the sending process, I am seeing the message that was sent in the slot connected to the readyRead signal. What have I done wrong? I would have thought this is perfectly possible.

    For example, Process A, sends

    {"msgType":"hb"}
    

    To Process B...Process B, receives:

    {"msgType":"hb"}
    

    Process B then sends:

    {"msgType":"ack"}
    

    back to Process A, but instead of receiving:

    {"msgType":"ack"}
    

    Process A is seeing the original:

    {"msgType":"hb"}
    

    Kind Regards,
    Sy

    1 Reply Last reply
    0
    • SPlattenS SPlatten

      @KroMignon , the only place that qdbg() sends the data to is to the Application Output and the log files. I'm pretty sure that process A isn't responsible for the HB Json message in the received buffer.

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by
      #12

      @SPlatten said in Two way comms via socket?:

      I'm pretty sure that process A isn't responsible for the HB Json message in the received buffer.

      I don't know your software, but I often use QTcpServer, QTcpSocket und QUdpSocket on Windows/Linux/Android systems with Qt 5.4 up to 5.12.
      I am sure they don't send themselves data, if B receiving data from A, then A have sent them and there is somewhere in the application a QTcpSocket::write() call.

      So up to you the search all write() calls in the application source code.
      I am also sure that if you comment out psckReceiver->write(arybytMsg); you will also get the request echoed on B.

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

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

        Hi,

        If you have a client server model, you might just be resending the message to all connected sockets.

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

        SPlattenS 1 Reply Last reply
        2
        • SGaistS SGaist

          Hi,

          If you have a client server model, you might just be resending the message to all connected sockets.

          SPlattenS Offline
          SPlattenS Offline
          SPlatten
          wrote on last edited by SPlatten
          #3

          @SGaist , thank you, presently I only have two processes A & B. A is listening and B connects to A then sends a message, when A receives the message is sends and acknowledgement message back to B. B doesn't seem to be getting this message but it does read the message sent to A.

          Kind Regards,
          Sy

          KroMignonK 1 Reply Last reply
          0
          • SPlattenS SPlatten

            @SGaist , thank you, presently I only have two processes A & B. A is listening and B connects to A then sends a message, when A receives the message is sends and acknowledgement message back to B. B doesn't seem to be getting this message but it does read the message sent to A.

            KroMignonK Offline
            KroMignonK Offline
            KroMignon
            wrote on last edited by
            #4

            @SPlatten said in Two way comms via socket?:

            B doesn't seem to be getting this message but it does read the message sent to A.

            Perhaps A is sending the wrong message!

            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

            SPlattenS 1 Reply Last reply
            0
            • KroMignonK KroMignon

              @SPlatten said in Two way comms via socket?:

              B doesn't seem to be getting this message but it does read the message sent to A.

              Perhaps A is sending the wrong message!

              SPlattenS Offline
              SPlattenS Offline
              SPlatten
              wrote on last edited by SPlatten
              #5

              @KroMignon , nope, I have checked and verified, A is receiving the correct message and A is also sending the correct response.

              This is a sample of what process A is logging:

              clsJSON::blnDecodeAccordingToType, found match to: blnDecodeHeartbeat
              clsJSON::blnDecodeAccordingToType, JSON: {"msgType":"hb","source":"f1"}
              blnDecodeHeartbeat: {"msgType":"hb","source":"f1"}
              clsModule::onSendAck: {"msgType":"ackhb","source":"f1"}
              

              In the above, the function blnDecodeAccordingToType looks at the received packet and identifies the callback to handle it, in this case blnDecodeHeartbeat, msgType with hb represents a heartbeat message. The source represents the module the message comes from, in this case f1. blnDecodeHeartbeat shows what message it is handling, this emits a signal to sendAck which is connected to the slot onSendAck. sendAck sends a message back to f1 with the msgType ackhb to acknowledge the received message type. However process B doesn't appear to be getting it.

              Let's put it another way, if I wanted to implement a polling scheme using QT sockets, how would I achieve that? Where B polls A, sending a request message and A answers back ?

              I've searched online for something similar and I couldn't find anything.

              Kind Regards,
              Sy

              KroMignonK 1 Reply Last reply
              0
              • SPlattenS SPlatten

                @KroMignon , nope, I have checked and verified, A is receiving the correct message and A is also sending the correct response.

                This is a sample of what process A is logging:

                clsJSON::blnDecodeAccordingToType, found match to: blnDecodeHeartbeat
                clsJSON::blnDecodeAccordingToType, JSON: {"msgType":"hb","source":"f1"}
                blnDecodeHeartbeat: {"msgType":"hb","source":"f1"}
                clsModule::onSendAck: {"msgType":"ackhb","source":"f1"}
                

                In the above, the function blnDecodeAccordingToType looks at the received packet and identifies the callback to handle it, in this case blnDecodeHeartbeat, msgType with hb represents a heartbeat message. The source represents the module the message comes from, in this case f1. blnDecodeHeartbeat shows what message it is handling, this emits a signal to sendAck which is connected to the slot onSendAck. sendAck sends a message back to f1 with the msgType ackhb to acknowledge the received message type. However process B doesn't appear to be getting it.

                Let's put it another way, if I wanted to implement a polling scheme using QT sockets, how would I achieve that? Where B polls A, sending a request message and A answers back ?

                I've searched online for something similar and I couldn't find anything.

                KroMignonK Offline
                KroMignonK Offline
                KroMignon
                wrote on last edited by
                #6

                @SPlatten said in Two way comms via socket?:

                nope, I have checked and verified, A is receiving the correct message and A is also sending the correct response.

                How did you verify this?
                Did you analyze TCP/IP traffic with WireShark or something equivalent?

                TCP protocol is using buffering and data transmission windowing to reduce overhead between payload and header.
                This means calling QTcpSocket::write() will only store the data into the output buffer of the TCP/IP stack.
                You have to call QTcpSocket::flush() to force data sending to counterpart.
                You could also use QTcpSocket::setSocketOption(QAbstractSocket::LowDelayOption, 1); to disable the Nagle's algorithm (cf. https://doc.qt.io/qt-5/qabstractsocket.html#SocketOption-enum)

                It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                SPlattenS 1 Reply Last reply
                4
                • KroMignonK KroMignon

                  @SPlatten said in Two way comms via socket?:

                  nope, I have checked and verified, A is receiving the correct message and A is also sending the correct response.

                  How did you verify this?
                  Did you analyze TCP/IP traffic with WireShark or something equivalent?

                  TCP protocol is using buffering and data transmission windowing to reduce overhead between payload and header.
                  This means calling QTcpSocket::write() will only store the data into the output buffer of the TCP/IP stack.
                  You have to call QTcpSocket::flush() to force data sending to counterpart.
                  You could also use QTcpSocket::setSocketOption(QAbstractSocket::LowDelayOption, 1); to disable the Nagle's algorithm (cf. https://doc.qt.io/qt-5/qabstractsocket.html#SocketOption-enum)

                  SPlattenS Offline
                  SPlattenS Offline
                  SPlatten
                  wrote on last edited by SPlatten
                  #7

                  @KroMignon , I dump the contents of the JSON object I am passing with the signal corresponds to the write operation. I have Wireshark so I'll fire it up and capture it.

                  [Edit]I've just used WireShark to capture Lookback:lo0 and I can see that one packet contains:

                  0000   1e 00 00 00 60 0a 1a 5c 00 3e 06 40 00 00 00 00   ....`..\.>.@....
                  0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                  0020   00 00 00 00 00 00 00 00 00 00 00 01 c1 13 1f bb   ................
                  0030   2e 63 a0 fc 81 9e 60 de 80 18 18 e3 00 46 00 00   .c....`......F..
                  0040   01 01 08 0a 17 02 26 3d 17 02 1e 6d 7b 22 6d 73   ......&=...m{"ms
                  0050   67 54 79 70 65 22 3a 22 68 62 22 2c 22 73 6f 75   gType":"hb","sou
                  0060   72 63 65 22 3a 22 66 31 22 7d                     rce":"f1"}
                  

                  After this another packet contains:

                  0000   1e 00 00 00 60 02 60 34 00 5f 06 40 00 00 00 00   ....`.`4._.@....
                  0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                  0020   00 00 00 00 00 00 00 00 00 00 00 01 1f bb c1 13   ................
                  0030   81 9e 60 de 2e 63 a1 1a 80 18 18 e2 00 67 00 00   ..`..c.......g..
                  0040   01 01 08 0a 17 02 26 40 17 02 26 3d 7b 22 6d 73   ......&@..&={"ms
                  0050   67 54 79 70 65 22 3a 22 68 62 22 2c 22 73 6f 75   gType":"hb","sou
                  0060   72 63 65 22 3a 22 66 31 22 7d 7b 22 6d 73 67 54   rce":"f1"}{"msgT
                  0070   79 70 65 22 3a 22 61 63 6b 68 62 22 2c 22 73 6f   ype":"ackhb","so
                  0080   75 72 63 65 22 3a 22 66 31 22 7d                  urce":"f1"}
                  

                  In the buffer it appears that the buffer contains the original message with the acknowledge packet after it...will look into this, but I'm not sure how this can be happening?

                  On looking into it, it seems I am getting both packets in the application that's expecting just the ack...Is this because both apps are reading the same connection asynchronously and the sender is checking for receipt of the data because the other application has read the data? If Yes, how can I prevent this happening?

                  Kind Regards,
                  Sy

                  KroMignonK 1 Reply Last reply
                  0
                  • SPlattenS SPlatten

                    @KroMignon , I dump the contents of the JSON object I am passing with the signal corresponds to the write operation. I have Wireshark so I'll fire it up and capture it.

                    [Edit]I've just used WireShark to capture Lookback:lo0 and I can see that one packet contains:

                    0000   1e 00 00 00 60 0a 1a 5c 00 3e 06 40 00 00 00 00   ....`..\.>.@....
                    0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                    0020   00 00 00 00 00 00 00 00 00 00 00 01 c1 13 1f bb   ................
                    0030   2e 63 a0 fc 81 9e 60 de 80 18 18 e3 00 46 00 00   .c....`......F..
                    0040   01 01 08 0a 17 02 26 3d 17 02 1e 6d 7b 22 6d 73   ......&=...m{"ms
                    0050   67 54 79 70 65 22 3a 22 68 62 22 2c 22 73 6f 75   gType":"hb","sou
                    0060   72 63 65 22 3a 22 66 31 22 7d                     rce":"f1"}
                    

                    After this another packet contains:

                    0000   1e 00 00 00 60 02 60 34 00 5f 06 40 00 00 00 00   ....`.`4._.@....
                    0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                    0020   00 00 00 00 00 00 00 00 00 00 00 01 1f bb c1 13   ................
                    0030   81 9e 60 de 2e 63 a1 1a 80 18 18 e2 00 67 00 00   ..`..c.......g..
                    0040   01 01 08 0a 17 02 26 40 17 02 26 3d 7b 22 6d 73   ......&@..&={"ms
                    0050   67 54 79 70 65 22 3a 22 68 62 22 2c 22 73 6f 75   gType":"hb","sou
                    0060   72 63 65 22 3a 22 66 31 22 7d 7b 22 6d 73 67 54   rce":"f1"}{"msgT
                    0070   79 70 65 22 3a 22 61 63 6b 68 62 22 2c 22 73 6f   ype":"ackhb","so
                    0080   75 72 63 65 22 3a 22 66 31 22 7d                  urce":"f1"}
                    

                    In the buffer it appears that the buffer contains the original message with the acknowledge packet after it...will look into this, but I'm not sure how this can be happening?

                    On looking into it, it seems I am getting both packets in the application that's expecting just the ack...Is this because both apps are reading the same connection asynchronously and the sender is checking for receipt of the data because the other application has read the data? If Yes, how can I prevent this happening?

                    KroMignonK Offline
                    KroMignonK Offline
                    KroMignon
                    wrote on last edited by
                    #8

                    @SPlatten said in Two way comms via socket?:

                    On looking into it, it seems I am getting both packets in the application that's expecting just the ack...Is this because both apps are reading the same connection asynchronously and the sender is checking for receipt of the data because the other application has read the data? If Yes, how can I prevent this happening?

                    What kind of socket do you use?
                    For me, there is no chance to do this with TCP sockets. The only explanation for me is that A is sending booth, reply and request. So for me, it looks like a software bug.

                    It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                    SPlattenS 1 Reply Last reply
                    1
                    • KroMignonK KroMignon

                      @SPlatten said in Two way comms via socket?:

                      On looking into it, it seems I am getting both packets in the application that's expecting just the ack...Is this because both apps are reading the same connection asynchronously and the sender is checking for receipt of the data because the other application has read the data? If Yes, how can I prevent this happening?

                      What kind of socket do you use?
                      For me, there is no chance to do this with TCP sockets. The only explanation for me is that A is sending booth, reply and request. So for me, it looks like a software bug.

                      SPlattenS Offline
                      SPlattenS Offline
                      SPlatten
                      wrote on last edited by SPlatten
                      #9

                      @KroMignon , Process B is using QTcpSocket, Process A is listening with QTcpServer. A is only sending the Ack, B is only sending the HB.

                      Part of Process A is to identify the type of message received, it then calls a function pointer specific to the decode type, in the case of HB:

                      bool blnDecodeHeartbeat(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                          clsModule* pModule = pDecodeSource(crobjJSON);
                          if ( pModule != nullptr ) {
                              pModule->updateHearbeat();
                          //Extract the message type from the message
                              qdbg() << "blnDecodeHeartbeat: " << QJsonDocument(crobjJSON).toJson(QJsonDocument::Compact);
                              emit pModule->sendAck(crobjJSON, psckReceiver);
                              return true;
                          }
                          return false;
                      }
                      

                      The sendAck signal is connected to the onSendAck slot:

                      void clsModule::onSendAck(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                          QJsonObject objAck(crobjJSON);
                          QJsonObject::const_iterator citrFound = crobjJSON.find(clsJSON::mscszMsgType);
                      
                          if ( citrFound != crobjJSON.end() ) {
                              QString strAck(clsJSON::mscszAck + citrFound.value().toString());
                              objAck.insert(clsJSON::mscszMsgType, strAck);
                              objAck.insert(clsJSON::mscszAddrTo, clsJSON::mscszXMLMPAM);
                      qdbg() << "clsModule::onSendAck: " << QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                              if ( mblnReady != true ) {
                                  sendLater(cstrGetAlias(), objAck);
                              } else if ( psckReceiver != nullptr
                                       && psckReceiver->state() == QAbstractSocket::ConnectedState ) {
                                  QByteArray arybytMsg;
                                  arybytMsg = QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                  psckReceiver->write(arybytMsg);
                              }
                          }
                      }
                      

                      Kind Regards,
                      Sy

                      KroMignonK 1 Reply Last reply
                      0
                      • SPlattenS SPlatten

                        @KroMignon , Process B is using QTcpSocket, Process A is listening with QTcpServer. A is only sending the Ack, B is only sending the HB.

                        Part of Process A is to identify the type of message received, it then calls a function pointer specific to the decode type, in the case of HB:

                        bool blnDecodeHeartbeat(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                            clsModule* pModule = pDecodeSource(crobjJSON);
                            if ( pModule != nullptr ) {
                                pModule->updateHearbeat();
                            //Extract the message type from the message
                                qdbg() << "blnDecodeHeartbeat: " << QJsonDocument(crobjJSON).toJson(QJsonDocument::Compact);
                                emit pModule->sendAck(crobjJSON, psckReceiver);
                                return true;
                            }
                            return false;
                        }
                        

                        The sendAck signal is connected to the onSendAck slot:

                        void clsModule::onSendAck(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                            QJsonObject objAck(crobjJSON);
                            QJsonObject::const_iterator citrFound = crobjJSON.find(clsJSON::mscszMsgType);
                        
                            if ( citrFound != crobjJSON.end() ) {
                                QString strAck(clsJSON::mscszAck + citrFound.value().toString());
                                objAck.insert(clsJSON::mscszMsgType, strAck);
                                objAck.insert(clsJSON::mscszAddrTo, clsJSON::mscszXMLMPAM);
                        qdbg() << "clsModule::onSendAck: " << QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                if ( mblnReady != true ) {
                                    sendLater(cstrGetAlias(), objAck);
                                } else if ( psckReceiver != nullptr
                                         && psckReceiver->state() == QAbstractSocket::ConnectedState ) {
                                    QByteArray arybytMsg;
                                    arybytMsg = QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                    psckReceiver->write(arybytMsg);
                                }
                            }
                        }
                        
                        KroMignonK Offline
                        KroMignonK Offline
                        KroMignon
                        wrote on last edited by
                        #10

                        @SPlatten said in Two way comms via socket?:

                        Process B is using QTcpSocket, Process A is listening with QTcpServer. A is only sending the Ack, B is only sending the HB.

                        According to TCP socket sniffer, I am pretty sure you are echoing the received message somewhere else, before calling blnDecodeHeartbeat().

                        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                        SPlattenS 1 Reply Last reply
                        0
                        • KroMignonK KroMignon

                          @SPlatten said in Two way comms via socket?:

                          Process B is using QTcpSocket, Process A is listening with QTcpServer. A is only sending the Ack, B is only sending the HB.

                          According to TCP socket sniffer, I am pretty sure you are echoing the received message somewhere else, before calling blnDecodeHeartbeat().

                          SPlattenS Offline
                          SPlattenS Offline
                          SPlatten
                          wrote on last edited by
                          #11

                          @KroMignon , the only place that qdbg() sends the data to is to the Application Output and the log files. I'm pretty sure that process A isn't responsible for the HB Json message in the received buffer.

                          Kind Regards,
                          Sy

                          KroMignonK 1 Reply Last reply
                          0
                          • SPlattenS SPlatten

                            @KroMignon , the only place that qdbg() sends the data to is to the Application Output and the log files. I'm pretty sure that process A isn't responsible for the HB Json message in the received buffer.

                            KroMignonK Offline
                            KroMignonK Offline
                            KroMignon
                            wrote on last edited by
                            #12

                            @SPlatten said in Two way comms via socket?:

                            I'm pretty sure that process A isn't responsible for the HB Json message in the received buffer.

                            I don't know your software, but I often use QTcpServer, QTcpSocket und QUdpSocket on Windows/Linux/Android systems with Qt 5.4 up to 5.12.
                            I am sure they don't send themselves data, if B receiving data from A, then A have sent them and there is somewhere in the application a QTcpSocket::write() call.

                            So up to you the search all write() calls in the application source code.
                            I am also sure that if you comment out psckReceiver->write(arybytMsg); you will also get the request echoed on B.

                            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                            SPlattenS 1 Reply Last reply
                            2
                            • KroMignonK KroMignon

                              @SPlatten said in Two way comms via socket?:

                              I'm pretty sure that process A isn't responsible for the HB Json message in the received buffer.

                              I don't know your software, but I often use QTcpServer, QTcpSocket und QUdpSocket on Windows/Linux/Android systems with Qt 5.4 up to 5.12.
                              I am sure they don't send themselves data, if B receiving data from A, then A have sent them and there is somewhere in the application a QTcpSocket::write() call.

                              So up to you the search all write() calls in the application source code.
                              I am also sure that if you comment out psckReceiver->write(arybytMsg); you will also get the request echoed on B.

                              SPlattenS Offline
                              SPlattenS Offline
                              SPlatten
                              wrote on last edited by SPlatten
                              #13

                              @KroMignon , Process A is listening to QHostAddress::Any on port 8123, Process B is connecting to the localhost IP address and port 8123. Both processes are sending data to the same address and port, so what's stopping Process A from receiving its own traffic which seems to be the case?

                              I've now added an addrTo field in the JSON packets which allows the receivers to identify if the packet is addressed to the receiver or not.

                              [Edit] Just found the bug, I was indeed echoing back the received data from my decoder. Thank you for your help.

                              Kind Regards,
                              Sy

                              KroMignonK 1 Reply Last reply
                              0
                              • SPlattenS SPlatten

                                @KroMignon , Process A is listening to QHostAddress::Any on port 8123, Process B is connecting to the localhost IP address and port 8123. Both processes are sending data to the same address and port, so what's stopping Process A from receiving its own traffic which seems to be the case?

                                I've now added an addrTo field in the JSON packets which allows the receivers to identify if the packet is addressed to the receiver or not.

                                [Edit] Just found the bug, I was indeed echoing back the received data from my decoder. Thank you for your help.

                                KroMignonK Offline
                                KroMignonK Offline
                                KroMignon
                                wrote on last edited by
                                #14

                                @SPlatten said in Two way comms via socket?:

                                , Process A is listening to QHostAddress::Any on port 8123, Process B is connecting to the localhost IP address and port 8123. Both processes are sending data to the same address and port, so what's stopping Process A from receiving its own traffic which seems to be the case?

                                You are using TCP sockets, TCP is an unicast protocol. There is no chance of receiving data from outside. With UDP socket you could send data to any open UDP port, but you are using TCP. So you need to be connected to be able to send data on the socket.

                                The TCP server socket may listen on any IP address, but when TCP client is connected, then the connection is between 2 endpoints (IP Adress + TCP port number):

                                • one for the client side
                                • one for the server side

                                And each endpoint is hold by a QTcpSocket instance, once again you can only receive what you are sending. And only the connected endpoints can send data.

                                Like Sherlock Holmes (aka Arthur Conan Doyle) say: "It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth."

                                It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                SPlattenS 1 Reply Last reply
                                3
                                • KroMignonK KroMignon

                                  @SPlatten said in Two way comms via socket?:

                                  , Process A is listening to QHostAddress::Any on port 8123, Process B is connecting to the localhost IP address and port 8123. Both processes are sending data to the same address and port, so what's stopping Process A from receiving its own traffic which seems to be the case?

                                  You are using TCP sockets, TCP is an unicast protocol. There is no chance of receiving data from outside. With UDP socket you could send data to any open UDP port, but you are using TCP. So you need to be connected to be able to send data on the socket.

                                  The TCP server socket may listen on any IP address, but when TCP client is connected, then the connection is between 2 endpoints (IP Adress + TCP port number):

                                  • one for the client side
                                  • one for the server side

                                  And each endpoint is hold by a QTcpSocket instance, once again you can only receive what you are sending. And only the connected endpoints can send data.

                                  Like Sherlock Holmes (aka Arthur Conan Doyle) say: "It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth."

                                  SPlattenS Offline
                                  SPlattenS Offline
                                  SPlatten
                                  wrote on last edited by
                                  #15

                                  @KroMignon , the next issue I have is that having sorted this issue.

                                  Process A is listening for messages on any local address on port 8123
                                  Process B sends a message to A.
                                  Process A receives the message and responds with an acknowledge message, I can see from the signals that the bytesWritten matches the message length.

                                  But Process B isn't receiving the message from A, what could explain this?

                                  This is the decode that Process A uses for the received message and sends the response:

                                  bool blnDecodeHeartbeat(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                                      clsModule* pModule = pDecodeSource(crobjJSON);
                                      if ( pModule != nullptr ) {
                                          pModule->updateHearbeat();
                                      //Extract the message type from the message
                                          qdbg() << "blnDecodeHeartbeat: " << QJsonDocument(crobjJSON).toJson(QJsonDocument::Compact);
                                          emit pModule->sendAck(crobjJSON, psckReceiver);
                                          return true;
                                      }
                                      return false;
                                  }
                                  

                                  sendAck is a signal connected to slot:

                                  void clsModule::onSendAck(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                                      QJsonObject::const_iterator citrFound = crobjJSON.find(clsJSON::mscszMsgType);
                                  
                                      if ( citrFound == crobjJSON.end() ) {
                                          return;
                                      }
                                      QString strAck(clsJSON::mscszAck + citrFound.value().toString());
                                      QJsonObject objAck;
                                      objAck.insert(clsJSON::mscszAddrTo, cstrGetAlias());
                                      objAck.insert(clsJSON::mscszMsgType, strAck);
                                      objAck.insert(clsJSON::mscszSource, clsJSON::mscszXMLMPAM);
                                  qdbg() << "clsModule::onSendAck: " << QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                      if ( mblnReady != true ) {
                                          sendLater(cstrGetAlias(), objAck);
                                      } else if ( psckReceiver != nullptr
                                               && psckReceiver->state() == QAbstractSocket::ConnectedState ) {
                                          QByteArray arybytMsg;
                                          arybytMsg = QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                          psckReceiver->write(arybytMsg);
                                      }
                                  }
                                  

                                  mblnReady is true, psckReceiver is the instance of QTcpSocket that received the message being acknowledged.

                                  Kind Regards,
                                  Sy

                                  KroMignonK 1 Reply Last reply
                                  0
                                  • SPlattenS SPlatten

                                    @KroMignon , the next issue I have is that having sorted this issue.

                                    Process A is listening for messages on any local address on port 8123
                                    Process B sends a message to A.
                                    Process A receives the message and responds with an acknowledge message, I can see from the signals that the bytesWritten matches the message length.

                                    But Process B isn't receiving the message from A, what could explain this?

                                    This is the decode that Process A uses for the received message and sends the response:

                                    bool blnDecodeHeartbeat(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                                        clsModule* pModule = pDecodeSource(crobjJSON);
                                        if ( pModule != nullptr ) {
                                            pModule->updateHearbeat();
                                        //Extract the message type from the message
                                            qdbg() << "blnDecodeHeartbeat: " << QJsonDocument(crobjJSON).toJson(QJsonDocument::Compact);
                                            emit pModule->sendAck(crobjJSON, psckReceiver);
                                            return true;
                                        }
                                        return false;
                                    }
                                    

                                    sendAck is a signal connected to slot:

                                    void clsModule::onSendAck(const QJsonObject& crobjJSON, QTcpSocket* psckReceiver) {
                                        QJsonObject::const_iterator citrFound = crobjJSON.find(clsJSON::mscszMsgType);
                                    
                                        if ( citrFound == crobjJSON.end() ) {
                                            return;
                                        }
                                        QString strAck(clsJSON::mscszAck + citrFound.value().toString());
                                        QJsonObject objAck;
                                        objAck.insert(clsJSON::mscszAddrTo, cstrGetAlias());
                                        objAck.insert(clsJSON::mscszMsgType, strAck);
                                        objAck.insert(clsJSON::mscszSource, clsJSON::mscszXMLMPAM);
                                    qdbg() << "clsModule::onSendAck: " << QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                        if ( mblnReady != true ) {
                                            sendLater(cstrGetAlias(), objAck);
                                        } else if ( psckReceiver != nullptr
                                                 && psckReceiver->state() == QAbstractSocket::ConnectedState ) {
                                            QByteArray arybytMsg;
                                            arybytMsg = QJsonDocument(objAck).toJson(QJsonDocument::Compact);
                                            psckReceiver->write(arybytMsg);
                                        }
                                    }
                                    

                                    mblnReady is true, psckReceiver is the instance of QTcpSocket that received the message being acknowledged.

                                    KroMignonK Offline
                                    KroMignonK Offline
                                    KroMignon
                                    wrote on last edited by
                                    #16

                                    @SPlatten said in Two way comms via socket?:

                                    But Process B isn't receiving the message from A, what could explain this?

                                    According to the TCP sniffer outputs done before, A is sending the reply.
                                    So the problem is on B side I guess.

                                    It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                    SPlattenS 1 Reply Last reply
                                    0
                                    • KroMignonK KroMignon

                                      @SPlatten said in Two way comms via socket?:

                                      But Process B isn't receiving the message from A, what could explain this?

                                      According to the TCP sniffer outputs done before, A is sending the reply.
                                      So the problem is on B side I guess.

                                      SPlattenS Offline
                                      SPlattenS Offline
                                      SPlatten
                                      wrote on last edited by SPlatten
                                      #17

                                      @KroMignon , thank you, I can see that, but what could it be?

                                      Will launch WireShark and take a closer look.

                                      [Edit] From WireShark:

                                      0000   1e 00 00 00 60 03 01 5f 00 5a 06 40 00 00 00 00   ....`.._.Z.@....
                                      0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                      0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                      0030   51 fb 74 49 39 86 cf 4c 80 18 18 e3 00 62 00 00   Q.tI9..L.....b..
                                      0040   01 01 08 0a 00 d9 d7 67 00 d9 d7 63 7b 22 61 64   .......g...c{"ad
                                      0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                      0060   22 6d 73 67 54 79 70 65 22 3a 22 72 65 61 64 79   "msgType":"ready
                                      0070   22 2c 22 73 6f 75 72 63 65 22 3a 22 6d 64 46 69   ","source":"mdFi
                                      0080   6c 65 49 4f 22 7d                                 leIO"}
                                      

                                      This is the initial module B message declaring that the module is now ready.

                                      0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                      0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                      0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                      0030   51 fb 74 83 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.t.9..L....._..
                                      0040   01 01 08 0a 00 d9 de cf 00 d9 d7 67 7b 22 61 64   ...........g{"ad
                                      0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                      0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                      0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                      0080   4f 22 7d                                          O"}
                                      

                                      This is the heartbeat message sent from B to A.

                                      0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                      0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                      0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                      0030   51 fb 74 f1 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.t.9..L....._..
                                      0040   01 01 08 0a 00 d9 ee 18 00 d9 e6 4a 7b 22 61 64   ...........J{"ad
                                      0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                      0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                      0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                      0080   4f 22 7d                                          O"}
                                      

                                      Another heartbeat message again from B to A these are sent once every second.

                                      0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                      0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                      0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                      0030   51 fb 75 28 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.u(9..L....._..
                                      0040   01 01 08 0a 00 d9 f5 e7 00 d9 ee 18 7b 22 61 64   ............{"ad
                                      0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                      0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                      0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                      0080   4f 22 7d                                          O"}
                                      

                                      And another heartbeat message again B to A, there are plenty of these but no acknowledgements.

                                      So the question changes now, since A is telling me that it has written 55 bytes with the bytesWritten signal, where is the data going?

                                      Kind Regards,
                                      Sy

                                      KroMignonK 2 Replies Last reply
                                      0
                                      • SPlattenS SPlatten

                                        @KroMignon , thank you, I can see that, but what could it be?

                                        Will launch WireShark and take a closer look.

                                        [Edit] From WireShark:

                                        0000   1e 00 00 00 60 03 01 5f 00 5a 06 40 00 00 00 00   ....`.._.Z.@....
                                        0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                        0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                        0030   51 fb 74 49 39 86 cf 4c 80 18 18 e3 00 62 00 00   Q.tI9..L.....b..
                                        0040   01 01 08 0a 00 d9 d7 67 00 d9 d7 63 7b 22 61 64   .......g...c{"ad
                                        0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                        0060   22 6d 73 67 54 79 70 65 22 3a 22 72 65 61 64 79   "msgType":"ready
                                        0070   22 2c 22 73 6f 75 72 63 65 22 3a 22 6d 64 46 69   ","source":"mdFi
                                        0080   6c 65 49 4f 22 7d                                 leIO"}
                                        

                                        This is the initial module B message declaring that the module is now ready.

                                        0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                        0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                        0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                        0030   51 fb 74 83 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.t.9..L....._..
                                        0040   01 01 08 0a 00 d9 de cf 00 d9 d7 67 7b 22 61 64   ...........g{"ad
                                        0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                        0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                        0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                        0080   4f 22 7d                                          O"}
                                        

                                        This is the heartbeat message sent from B to A.

                                        0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                        0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                        0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                        0030   51 fb 74 f1 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.t.9..L....._..
                                        0040   01 01 08 0a 00 d9 ee 18 00 d9 e6 4a 7b 22 61 64   ...........J{"ad
                                        0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                        0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                        0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                        0080   4f 22 7d                                          O"}
                                        

                                        Another heartbeat message again from B to A these are sent once every second.

                                        0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                        0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                        0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                        0030   51 fb 75 28 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.u(9..L....._..
                                        0040   01 01 08 0a 00 d9 f5 e7 00 d9 ee 18 7b 22 61 64   ............{"ad
                                        0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                        0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                        0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                        0080   4f 22 7d                                          O"}
                                        

                                        And another heartbeat message again B to A, there are plenty of these but no acknowledgements.

                                        So the question changes now, since A is telling me that it has written 55 bytes with the bytesWritten signal, where is the data going?

                                        KroMignonK Offline
                                        KroMignonK Offline
                                        KroMignon
                                        wrote on last edited by KroMignon
                                        #18

                                        @SPlatten said in Two way comms via socket?:

                                        thank you, I can see that, but what could it be?

                                        I can only guess, I don't know how you set up the QTcpSocket instance on server side:

                                        • You did not connect readyRead() signal
                                        • the instance have been destroyed
                                        • the QEventLoop used by the thread which is hosting the instance is locked
                                        • there is a bug in the slots attached to readyRead() signal

                                        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                        SPlattenS 1 Reply Last reply
                                        0
                                        • KroMignonK KroMignon

                                          @SPlatten said in Two way comms via socket?:

                                          thank you, I can see that, but what could it be?

                                          I can only guess, I don't know how you set up the QTcpSocket instance on server side:

                                          • You did not connect readyRead() signal
                                          • the instance have been destroyed
                                          • the QEventLoop used by the thread which is hosting the instance is locked
                                          • there is a bug in the slots attached to readyRead() signal
                                          SPlattenS Offline
                                          SPlattenS Offline
                                          SPlatten
                                          wrote on last edited by SPlatten
                                          #19

                                          @KroMignon , A connections:

                                          QTcpSocket* pSocket = new QTcpSocket();
                                          //Set the ID
                                          qdbg() << "clsServer::run";
                                          if( !pSocket->setSocketDescriptor(msckDescriptor) ) {
                                          //Something's wrong, we just emit a signal
                                              emit error(pSocket->error());
                                              return;
                                          }
                                          //Connect socket and signal
                                          mpsckIncoming = pSocket;
                                          QObject::connect(mpsckIncoming, &QAbstractSocket::errorOccurred
                                                          ,this, &clsServer::onErrorOccurred);
                                          QObject::connect(mpsckIncoming, &QAbstractSocket::disconnected
                                                          ,this, &clsServer::onDisconnected);
                                          QObject::connect(mpsckIncoming, &QAbstractSocket::readyRead
                                                          ,this, &clsServer::onReadyRead);
                                          

                                          Initialisation on B of QTcpSocket:

                                          mpsckReceiver = new QTcpSocket();
                                          QObject::connect(mpsckReceiver, &QAbstractSocket::bytesWritten
                                                          ,this, &clsModule::onBytesWritten);
                                          QObject::connect(mpsckReceiver, &QAbstractSocket::connected
                                                          ,this, &clsModule::onConnected);
                                          QObject::connect(mpsckReceiver, &QAbstractSocket::readyRead
                                                          ,this, &clsModule::onReadyRead);
                                          QObject::connect(mpsckReceiver, &QAbstractSocket::disconnected
                                                          ,this, &clsModule::onDisconnected);
                                          if ( mpsckReceiver != nullptr && muint16Port > 0 ) {
                                              QAbstractSocket::SocketState eState = mpsckReceiver->state();
                                          
                                              if ( eState != QAbstractSocket::HostLookupState
                                                && eState != QAbstractSocket::ConnectedState
                                                && eState != QAbstractSocket::ConnectingState ) {
                                                  mpsckReceiver->connectToHost(QHostInfo::localHostName(), muint16Port);
                                              }
                                          }
                                          

                                          Kind Regards,
                                          Sy

                                          1 Reply Last reply
                                          0
                                          • SPlattenS SPlatten

                                            @KroMignon , thank you, I can see that, but what could it be?

                                            Will launch WireShark and take a closer look.

                                            [Edit] From WireShark:

                                            0000   1e 00 00 00 60 03 01 5f 00 5a 06 40 00 00 00 00   ....`.._.Z.@....
                                            0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                            0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                            0030   51 fb 74 49 39 86 cf 4c 80 18 18 e3 00 62 00 00   Q.tI9..L.....b..
                                            0040   01 01 08 0a 00 d9 d7 67 00 d9 d7 63 7b 22 61 64   .......g...c{"ad
                                            0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                            0060   22 6d 73 67 54 79 70 65 22 3a 22 72 65 61 64 79   "msgType":"ready
                                            0070   22 2c 22 73 6f 75 72 63 65 22 3a 22 6d 64 46 69   ","source":"mdFi
                                            0080   6c 65 49 4f 22 7d                                 leIO"}
                                            

                                            This is the initial module B message declaring that the module is now ready.

                                            0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                            0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                            0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                            0030   51 fb 74 83 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.t.9..L....._..
                                            0040   01 01 08 0a 00 d9 de cf 00 d9 d7 67 7b 22 61 64   ...........g{"ad
                                            0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                            0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                            0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                            0080   4f 22 7d                                          O"}
                                            

                                            This is the heartbeat message sent from B to A.

                                            0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                            0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                            0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                            0030   51 fb 74 f1 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.t.9..L....._..
                                            0040   01 01 08 0a 00 d9 ee 18 00 d9 e6 4a 7b 22 61 64   ...........J{"ad
                                            0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                            0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                            0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                            0080   4f 22 7d                                          O"}
                                            

                                            Another heartbeat message again from B to A these are sent once every second.

                                            0000   1e 00 00 00 60 03 01 5f 00 57 06 40 00 00 00 00   ....`.._.W.@....
                                            0010   00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
                                            0020   00 00 00 00 00 00 00 00 00 00 00 01 c5 84 1f bb   ................
                                            0030   51 fb 75 28 39 86 cf 4c 80 18 18 e3 00 5f 00 00   Q.u(9..L....._..
                                            0040   01 01 08 0a 00 d9 f5 e7 00 d9 ee 18 7b 22 61 64   ............{"ad
                                            0050   64 72 54 6f 22 3a 22 58 4d 4c 4d 50 41 4d 22 2c   drTo":"XMLMPAM",
                                            0060   22 6d 73 67 54 79 70 65 22 3a 22 68 62 22 2c 22   "msgType":"hb","
                                            0070   73 6f 75 72 63 65 22 3a 22 6d 64 46 69 6c 65 49   source":"mdFileI
                                            0080   4f 22 7d                                          O"}
                                            

                                            And another heartbeat message again B to A, there are plenty of these but no acknowledgements.

                                            So the question changes now, since A is telling me that it has written 55 bytes with the bytesWritten signal, where is the data going?

                                            KroMignonK Offline
                                            KroMignonK Offline
                                            KroMignon
                                            wrote on last edited by KroMignon
                                            #20

                                            @SPlatten said in Two way comms via socket?:

                                            So the question changes now, since A is telling me that it has written 55 bytes with the bytesWritten signal, where is the data going?

                                            Into the TCP socket output buffer, did you disable Naggle's algorithm or do a QTcpSocket::flush()?

                                            [EDIT] By the way, are you sure you are capturing the right traffic on WireShark? (tcp port 8123)

                                            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                            SPlattenS 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