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.7k 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.
  • R Redman

    @J-Hilk Is there anything you can recommend for me to read to get a better understanding regarding this topic?
    While I understand your statement, this still leaves open my question regarding any incompatibilities between python and c++.

    J.HilkJ Offline
    J.HilkJ Offline
    J.Hilk
    Moderators
    wrote on last edited by J.Hilk
    #4

    @Redman I'm afraid most of my experience is from personally falling into such pits myself :D

    But for this type punning case I think this video might be a good source, its part of my link collection:
    https://youtu.be/_qzMpk-22cc


    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
    1
    • R Redman has marked this topic as solved on
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #5

      Fix your python code so it sends the struct with the correct size for the members. Or adjust your code to read uint32 for every part. Normally there is a spec where you define the format on the wire.

      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

        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.

        JonBJ Online
        JonBJ Online
        JonB
        wrote on last edited by
        #6

        @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 1 Reply Last reply
        1
        • GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #7

          or just use gRPC or an alternative.

          1 Reply Last reply
          0
          • R Offline
            R Offline
            Redman
            wrote on last edited by
            #8

            The problem seems to be the byte-alignment for the struct. The previously used c++ app that sent the packets used MSVC aswell as I do.

            #pragma pack(push, 1)
            struct Coordinate {
               quint32 id;
               quint16 mode;
               qint32 x;
               quint64 y;
               qint32 z;
            };
            #pragma pack(pop)
            

            Fixed the problem.

            1 Reply Last reply
            0
            • J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #9

              calling that fixed is generous :P

              But if you're satisfied! 👍


              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
              0
              • JonBJ JonB

                @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 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?

                JonBJ 1 Reply Last reply
                0
                • J.HilkJ J.Hilk

                  calling that fixed is generous :P

                  But if you're satisfied! 👍

                  R Offline
                  R Offline
                  Redman
                  wrote on 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?

                  jsulmJ J.HilkJ 2 Replies Last reply
                  0
                  • R Redman

                    @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?

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on 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
                    3
                    • jsulmJ jsulm

                      @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 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

                        @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.HilkJ Offline
                        J.HilkJ Offline
                        J.Hilk
                        Moderators
                        wrote on 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
                        2
                        • J.HilkJ J.Hilk

                          @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 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.HilkJ 1 Reply Last reply
                          0
                          • jsulmJ Offline
                            jsulmJ Offline
                            jsulm
                            Lifetime Qt Champion
                            wrote on 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
                            1
                            • jsulmJ jsulm

                              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 last edited by
                              #17

                              @jsulm Thats why we tested both :)

                              1 Reply Last reply
                              0
                              • R Redman

                                @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.HilkJ Offline
                                J.HilkJ Offline
                                J.Hilk
                                Moderators
                                wrote on 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
                                • Christian EhrlicherC Offline
                                  Christian EhrlicherC Offline
                                  Christian Ehrlicher
                                  Lifetime Qt Champion
                                  wrote on 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
                                  2
                                  • R Redman

                                    @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?

                                    JonBJ Online
                                    JonBJ Online
                                    JonB
                                    wrote on 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
                                    • Christian EhrlicherC Christian Ehrlicher

                                      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 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.HilkJ Christian EhrlicherC 2 Replies Last reply
                                      0
                                      • R Redman

                                        @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.HilkJ Offline
                                        J.HilkJ Offline
                                        J.Hilk
                                        Moderators
                                        wrote on 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

                                          @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 :)

                                          Christian EhrlicherC Offline
                                          Christian EhrlicherC Offline
                                          Christian Ehrlicher
                                          Lifetime Qt Champion
                                          wrote on 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
                                          0

                                          • Login

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