Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. reinterpret_cast for received tcp packets
QtWS25 Last Chance

reinterpret_cast for received tcp packets

Scheduled Pinned Locked Moved Solved C++ Gurus
26 Posts 7 Posters 1.8k 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.
  • J JonB
    14 Jan 2025, 15:58

    @Redman said in reinterpret_cast for received tcp packets:

    No need for checking if the tcpSocker buffer is empty or if the available bytes in the buffer are only partially tansmitted etc.etc. Simply readAll bytes and cast it to the desired struct.

    Are you doing this as the communication runs along during the program, or only at the end after you have closed the socket? Assuming it's as you go along, how do you know that readAll() returns all bytes which might have been sent? It only guarantees to return 1 byte when readyRead() signal is fired, you have no guarantee any further bytes are there. The fact that it seems to work in some situation does not mean it won't go wrong in another. This has nothing to do with the casting.

    What do you use in Python to pack the data and send it, and how that compares to your struct's size/order/padding? What endian-ness is the sender machine and order of bytes sent?

    R Offline
    R Offline
    Redman
    wrote on 15 Jan 2025, 07:50 last edited by
    #10

    @JonB I do this during the whole execution time of my application. The tcp packet size is only 22 bytes, so fairly small.
    How would I go about making sure I get all the bytes out of the buffer?

    J 1 Reply Last reply 15 Jan 2025, 08:45
    0
    • J J.Hilk
      15 Jan 2025, 07:45

      calling that fixed is generous :P

      But if you're satisfied! 👍

      R Offline
      R Offline
      Redman
      wrote on 15 Jan 2025, 07:51 last edited by
      #11

      @J-Hilk As far as I understood it either its me who has to adjust or the sender. Why would you consider this to be a generous definition of fixed?

      J J 2 Replies Last reply 15 Jan 2025, 07:52
      0
      • R Redman
        15 Jan 2025, 07:51

        @J-Hilk As far as I understood it either its me who has to adjust or the sender. Why would you consider this to be a generous definition of fixed?

        J Offline
        J Offline
        jsulm
        Lifetime Qt Champion
        wrote on 15 Jan 2025, 07:52 last edited by
        #12

        @Redman said in reinterpret_cast for received tcp packets:

        Why would you consider this to be a generous definition of fixed?

        What about indianess?

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        R 1 Reply Last reply 15 Jan 2025, 07:56
        3
        • J jsulm
          15 Jan 2025, 07:52

          @Redman said in reinterpret_cast for received tcp packets:

          Why would you consider this to be a generous definition of fixed?

          What about indianess?

          R Offline
          R Offline
          Redman
          wrote on 15 Jan 2025, 07:56 last edited by Redman
          #13

          @jsulm Since both participants are Windows, little-endian is to be assumed. We did in fact switch to big-endian for each part of the message. This resulted in the first 2 parts not being recognized as a 1 anymore.

          The fact, that in the 3rd part a 1 was sent but was cast to a 65536 indicates the byte-alignment problem.
          Now Im not sure why @J-Hilk said it was a generous definition of fixed.

          1 Reply Last reply
          0
          • R Redman
            15 Jan 2025, 07:51

            @J-Hilk As far as I understood it either its me who has to adjust or the sender. Why would you consider this to be a generous definition of fixed?

            J Offline
            J Offline
            J.Hilk
            Moderators
            wrote on 15 Jan 2025, 07:59 last edited by
            #14

            @Redman said in reinterpret_cast for received tcp packets:

            Why would you consider this to be a generous definition of fixed?

            what about different compiler? pragma is highly depending on compiler and compiler version

            also casting a char* to a struct is still UB and just a dud waiting to explode


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            R 1 Reply Last reply 15 Jan 2025, 08:07
            2
            • J J.Hilk
              15 Jan 2025, 07:59

              @Redman said in reinterpret_cast for received tcp packets:

              Why would you consider this to be a generous definition of fixed?

              what about different compiler? pragma is highly depending on compiler and compiler version

              also casting a char* to a struct is still UB and just a dud waiting to explode

              R Offline
              R Offline
              Redman
              wrote on 15 Jan 2025, 08:07 last edited by
              #15

              @J-Hilk Since there are no plans of switching to a different Compiler than MSVC I did not consider that.
              I would assume that

              #pragma pack(push, 1)
              #pragma pack(pop)
              

              would do the same through all MSVC versions.

              Regarding that reinterpret_cast, I will, as you suggested, implement a ctor which takes a QByteArray.
              In fact, I already tried that out during figuring out what the actual problem was. To me the ctor looked "ugly".
              Doing byteArray.sliced(i,n) to retrieve the corresponding bytes and casting them to the desired type might be a quick thing to implement for such a small struct. But for larger structs this gets ugly very fast.

              Since c++ doesn't offer reflection, can I somehow use Qt's meta-object system to achieve a dynamic construction of my object?

              J 1 Reply Last reply 15 Jan 2025, 08:29
              0
              • J Offline
                J Offline
                jsulm
                Lifetime Qt Champion
                wrote on 15 Jan 2025, 08:08 last edited by
                #16

                I also would not assume indianess based on operating system. Windows also runs on ARM and ARM can be both big or little.

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                R 1 Reply Last reply 15 Jan 2025, 08:10
                1
                • J jsulm
                  15 Jan 2025, 08:08

                  I also would not assume indianess based on operating system. Windows also runs on ARM and ARM can be both big or little.

                  R Offline
                  R Offline
                  Redman
                  wrote on 15 Jan 2025, 08:10 last edited by
                  #17

                  @jsulm Thats why we tested both :)

                  1 Reply Last reply
                  0
                  • R Redman
                    15 Jan 2025, 08:07

                    @J-Hilk Since there are no plans of switching to a different Compiler than MSVC I did not consider that.
                    I would assume that

                    #pragma pack(push, 1)
                    #pragma pack(pop)
                    

                    would do the same through all MSVC versions.

                    Regarding that reinterpret_cast, I will, as you suggested, implement a ctor which takes a QByteArray.
                    In fact, I already tried that out during figuring out what the actual problem was. To me the ctor looked "ugly".
                    Doing byteArray.sliced(i,n) to retrieve the corresponding bytes and casting them to the desired type might be a quick thing to implement for such a small struct. But for larger structs this gets ugly very fast.

                    Since c++ doesn't offer reflection, can I somehow use Qt's meta-object system to achieve a dynamic construction of my object?

                    J Offline
                    J Offline
                    J.Hilk
                    Moderators
                    wrote on 15 Jan 2025, 08:29 last edited by
                    #18

                    @Redman I would suggest using QDataStream


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on 15 Jan 2025, 08:39 last edited by
                      #19

                      Casting a struct to a received bunch of bytes is not correct. It may work now but fail as soon as a small piece changes. Therefore you have to describe the bytes on the paket (e.g. in an interface document) and decode them accordingly. Everything else is a hack.

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      R 1 Reply Last reply 15 Jan 2025, 09:08
                      2
                      • R Redman
                        15 Jan 2025, 07:50

                        @JonB I do this during the whole execution time of my application. The tcp packet size is only 22 bytes, so fairly small.
                        How would I go about making sure I get all the bytes out of the buffer?

                        J Offline
                        J Offline
                        JonB
                        wrote on 15 Jan 2025, 08:45 last edited by JonB
                        #20

                        @Redman said in reinterpret_cast for received tcp packets:

                        @JonB I do this during the whole execution time of my application. The tcp packet size is only 22 bytes, so fairly small.
                        How would I go about making sure I get all the bytes out of the buffer?

                        Assuming recEchoDataReady() is called as a slot from readyRead() signal, what you are supposed to do is append the bytes to a "pending" buffer and then check whether the total number read into pending equals or exceeds the number you need/expect for your struct. If so remove those from pending. Not only might you be "short" (read only 1+ bytes when 22 expected), you might also "overflow" (read e.g. 32 when 22 wanted for one packet because it also finds some of the next packet), in which case that packet will "work" but the next packet will go wrong.

                        If you don't want to do this, because you believe it is always 22, you might at least put in a QASSERT(bytes_read == sizeof(Coordinate)) to verify that never goes wrong.

                        You say a lot about the struct size/packing/padding/endianness etc. at the receiving C++ side but did not answer how you send the data from the Python side. If I understand right you have looked at "the wire" or the bytes you receive and say they don't look right as raw bytes? In which case check the sender side. I believe you are saying that it used to work when the sender was C++ but now goes wrong when the sender is Python, in which case the receiver side is irrelevant and the bytes sent must be different, if that is really the case.

                        01:00:00:00:01:00:01:00:00:00:01:00:00:00:00:00:00:00:01:00:00:00

                        Unfortunately after casting that ByteArray to my struct I get following values

                        1 1 65536 65536 -1870011232

                        While this seems to contradict the statement that it is the sender side which has changed/gone wrong, I would examine this more closely. Off the top of my head that data buffer would not produce the (packed) struct values you say it does.

                        You also wrote at one point:

                        @Redman said in reinterpret_cast for received tcp packets:

                        Fixed the problem.

                        Does this mean you no longer have any problem sending/receiving the structure? You introduced the #pragma pack(push, 1), did that fix, was that at C++ receiver side or what did you do at Python sender side? Your C struct needs to be packed if you expect it to be 22 bytes size.

                        1 Reply Last reply
                        2
                        • C Christian Ehrlicher
                          15 Jan 2025, 08:39

                          Casting a struct to a received bunch of bytes is not correct. It may work now but fail as soon as a small piece changes. Therefore you have to describe the bytes on the paket (e.g. in an interface document) and decode them accordingly. Everything else is a hack.

                          R Offline
                          R Offline
                          Redman
                          wrote on 15 Jan 2025, 09:08 last edited by
                          #21

                          @Christian-Ehrlicher The interface is well documented and both sites agreed to it. So there will be no change to that without further discussion between me and our partner :)

                          J C 2 Replies Last reply 15 Jan 2025, 09:20
                          0
                          • R Redman
                            15 Jan 2025, 09:08

                            @Christian-Ehrlicher The interface is well documented and both sites agreed to it. So there will be no change to that without further discussion between me and our partner :)

                            J Offline
                            J Offline
                            J.Hilk
                            Moderators
                            wrote on 15 Jan 2025, 09:20 last edited by
                            #22

                            @Redman said in reinterpret_cast for received tcp packets:

                            The interface is well documented and both sites agreed to it. So there will be no change to that

                            alt text


                            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                            Q: What's that?
                            A: It's blue light.
                            Q: What does it do?
                            A: It turns blue.

                            1 Reply Last reply
                            3
                            • R Redman
                              15 Jan 2025, 09:08

                              @Christian-Ehrlicher The interface is well documented and both sites agreed to it. So there will be no change to that without further discussion between me and our partner :)

                              C Offline
                              C Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on 15 Jan 2025, 09:31 last edited by
                              #23

                              @Redman said in reinterpret_cast for received tcp packets:

                              The interface is well documented and both sites agreed to it.

                              Then you would not have asked any of the questions above nor any problems wrt connecting to another process.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              R 1 Reply Last reply 15 Jan 2025, 13:41
                              0
                              • C Christian Ehrlicher
                                15 Jan 2025, 09:31

                                @Redman said in reinterpret_cast for received tcp packets:

                                The interface is well documented and both sites agreed to it.

                                Then you would not have asked any of the questions above nor any problems wrt connecting to another process.

                                R Offline
                                R Offline
                                Redman
                                wrote on 15 Jan 2025, 13:41 last edited by
                                #24

                                @Christian-Ehrlicher And you live in a perfect world where no problems occur? :)

                                C 1 Reply Last reply 15 Jan 2025, 21:25
                                0
                                • R Redman
                                  15 Jan 2025, 13:41

                                  @Christian-Ehrlicher And you live in a perfect world where no problems occur? :)

                                  C Offline
                                  C Offline
                                  Christian Ehrlicher
                                  Lifetime Qt Champion
                                  wrote on 15 Jan 2025, 21:25 last edited by
                                  #25

                                  @Redman said in reinterpret_cast for received tcp packets:

                                  And you live in a perfect world where no problems occur?

                                  No, but your questions/problem revealed a basic lack of a "well documented" interface.

                                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                  Visit the Qt Academy at https://academy.qt.io/catalog

                                  1 Reply Last reply
                                  0
                                  • R Redman
                                    14 Jan 2025, 13:55

                                    Hello,

                                    I am developing an app on a 64bit windows machine.
                                    Im using Qt 6.8.1 and the c++20 standard.

                                    My app receives tcp packets from an app running on windows.
                                    I try to reinterpret_cast the packets into following struct.

                                    struct Coordinate {
                                       quint32 id;
                                       quint16 mode;
                                       qint32 x;
                                       quint64 y;
                                       qint32 z;
                                    };
                                    

                                    like followed

                                    void
                                    MyReceiver::recEchoDataReady() {
                                       QByteArray bytes = m_tcpServerClient->readAll();
                                       Coordinate pt = *reinterpret_cast<Coordinate*>(bytes.data());
                                    
                                       QMap<QString, QVariant> coord;
                                       coord.insert(QStringLiteral("ID"), pt.id);
                                       coord.insert(QStringLiteral("MODE"), pt.mode);
                                       coord.insert(QStringLiteral("X"), pt.x);
                                       coord.insert(QStringLiteral("Y"), pt.y);
                                       coord.insert(QStringLiteral("Z"), pt.z);
                                       emit echoDataReady(coord);
                                    }
                                    

                                    This approached worked flawlessly. We transmitted several millions of packets over the course of a couple of months without any problems. No need for checking if the tcpSocker buffer is empty or if the available bytes in the buffer are only partially tansmitted etc.etc. Simply readAll bytes and cast it to the desired struct.

                                    Recently there were changes made on the sender site of this protocol. They switched from a c++ app to a python app.
                                    Following you can see the hex representation of the bytes that arrived at my site. If you try to fit this into the struct you would think that the data within the struct would be 1 1 1 1 1.

                                    01:00:00:00:01:00:01:00:00:00:01:00:00:00:00:00:00:00:01:00:00:00
                                    

                                    Unfortunately after casting that ByteArray to my struct I get following values
                                    1 1 65536 65536 -1870011232

                                    Now I'm not sure if there are any incompatibilities between c++ and python datatype.
                                    I'm kinda stuck on this problem and have no clue why that is happening.

                                    If anyone has an idea on how to investigate this or provide a meaningfull explanation it would be greatly appreciated.

                                    S Offline
                                    S Offline
                                    SimonSchroeder
                                    wrote on 17 Jan 2025, 07:51 last edited by
                                    #26

                                    @Redman said in reinterpret_cast for received tcp packets:

                                    01:00:00:00:01:00:01:00:00:00:01:00:00:00:00:00:00:00:01:00:00:00

                                    This is what you'd expect for a packed struct (as you have figures out). It worked before because both sides were using C++ and so both sides were not using packed structs (so much about the "well defined protocol").

                                    In order to not have that problem @J-Hilk is right to write a constructor expecting a QByteArray. For sending you should also pack the members into a QByteArray yourself. This also makes you immune to the order of the members (which is only guaranteed by a very, very recent C++ standard). It is also common practice to order members from biggest to smallest, so you can adhere to alignment rules and still get the most compact representation. This would also solve your problem (on the C++ side; I don't know Python) that you don't have to explicitly pack the struct.

                                    1 Reply Last reply
                                    2

                                    19/26

                                    15 Jan 2025, 08:39

                                    • Login

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