Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QUdpSocket UDP socket writeDatagram readDatagram casting a struct (be carefull of padding)



  • Hello Mister/Miss QT,

    I want to SEND and RECEIVE a struct with QUdpSocket
    (as a translation of MSVS2013, see working code below)

    For example: the following struct:
    @
    typedef struct{
    unsigned short volgnummer;
    QByteArray payload;
    } UDPpacket;
    @

    I have working and tested code made in Visual Studio 2013 (see code below!) as that is what I'm really trying to achieve!!

    A simple (AND CORRECT) example of what I want to achieve:

    @
    void MyUDP::HelloUDP()
    {
    UDPpacket sendP;
    QByteArray send;
    send.append("UDP Message");
    sendP.payload = send;
    sendP.volgnummer = 1;

    socket->writeDatagram(SendP, QHostAddress::LocalHost, 1234);
    

    }

    void MyUDP::readPendingDatagrams()
    {
    UDPpacket receiveP;
    QByteArray buffer;
    QHostAddress sender;
    quint16 senderPort;
    buffer.resize(socket->pendingDatagramSize());
    socket->readDatagram(receiveP,SIZEOF(receiveP),&sender, &senderPort);
    }
    @

    Just using the normal way by means of QByteArray is working:

    @
    void MyUDP::HelloUDP()
    {
    UDPpacket sendP;
    QByteArray send;
    send.append("Als alles goed gaat is Error gelijk aan de hoeveelheid data dat is verzonden");
    sendP.payload = send;
    socket->writeDatagram(sendP.payload, QHostAddress::LocalHost, 1234);
    qDebug() << "Message: " << sendP.payload;
    }

    void MyUDP::readPendingDatagrams()
    {
    QByteArray buffer;
    QHostAddress sender;
    quint16 senderPort;
    buffer.resize(socket->pendingDatagramSize());
    socket->readDatagram(buffer.data(), buffer.size(),&sender, &senderPort);
    qDebug() << "Message: " << buffer;
    }
    @

    but as soon as I change it:

    @
    udp_packet tx_packet;
    udp_packet rx_packet;
    QByteArray Data;
    QByteArray buffer;
    QHostAddress sender;
    quint16 senderPort;

    tx_packet.volgnummer = (quint16)0;
    Data.append("Hello from UDP");
    tx_packet.real_payload = Data;
    
    socket->writeDatagram((char *)&tx_packet, sizeof(tx_packet), QHostAddress::LocalHost, 1234);
    socket->readDatagram ((char *)&rx_packet, sizeof(rx_packet), &sender, &senderPort);
    

    @

    I also tried const char * and even QByteArray * and several other options.

    [edit: added missing coding tags @ SGaist]



  • The following did the trick:

    memcpy(&tx_packet.MBC_payload, &buffer, sizeof(buffer));

    socket->writeDatagram((char *)&tx_packet, sizeof(tx_packet), QHostAddress::LocalHost, 1234);
    socket->readDatagram ((char *)&rx_packet, sizeof(rx_packet), &sender, &senderPort);

    qDebug() << "RECEIVED Message" << rx_packet.MBC_payload;
    gave the correct string back!

    BUT:

    • Watch out for PADDING of the compiler.
      (there are many items opened on this matter!

    AND

    certain functions will mess up (i.e. resizedatagram)

    So please be carefull



  • You should not really treat a QByteArray as raw data. Use the data() method to access a pointer to the data. I know this defeats your intention of having a struct with a header and then data, but this is not really a pattern that is very robust.

    A better mechanism would be to use a DataStream or TextStream wrapping a QByteArray to serialize your data and send the resulting byteArray over the wire.


Log in to reply