Nominate our 2022 Qt Champions!

Create QByteArray from a packet structure

  • Hi, I want to send a UDP packet to remote server, the packet content is already defined as a struct like this.

    struct MsgPacket {
    char header[20];
    unsigned short len;
    unsigned short cmd;
    unsigned short tag;
    unsigned short flag;
    unsigned int seq;
    char data[512];

    This struct is very useful, I can assign value to the specified position in the buffer.

    packet.len = (size);
    packet.cmd = (eventID);
    packet.tag = 0;
    packet.flag &= ~FLAG_REPLY;
    packet.flag |= FLAG_FINAL;
    packet.seq = 0;

    But there is still some annoying problem. While I was trying to send a packet by the Qt network module, I have to create a QByteArray like this.

    QByteArray datagram = QByteArray(static_cast<char*>((void*)&packet), sizeof(packet));
    senderSocket->writeDatagram(, datagram.size(), QHostAddress::Broadcast, REMOTE_PORT);

    I can replace the QByteArray with char pointer. But the char pointer is not inherited from a QObject. It would make some problem while sending it as signal parameter. So the QByteArray is much preferable.

    Can I improve this code more? It takes a lot of annoying cast and I feel this would not be a good coding style. Thank you in advance.

  • "QDataStream": is the right choice in your situation.

    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    out << QString("the answer is");
    out << (qint32)4

    And on other side:
    QByteArray data;
    QDataStream in(&data, QIODevice::ReadOnly);
    in >> >>;

  • THERE IS A BIG BUTT TO IT!!! A lot of desktop programmers forget that you do have to take into account the memory allocation on a byte level! So allocating a byte, a int and then a byte again will result in 3 addresses allocated with a lot of "empty" data. Think about it, first allocate a 1 byte (let's assume a 32 bits system) on a 4 byte address. Then an integer that will be 4 bytes in total, but on a new address. As last a new byte, so you think it will only consist of 6 bytes, but in processor world it would be 12!
    There is a way to fix it though. You need to make sure the struct is allocated without room in between. There are attributes to tell the compiler it has to crop the struct.
    #pragma pack(1) // 1 byte alignment
    typedef struct
    Have fun coding!

  • The data I want to send was binary data(struct), it is not string.

    12 34 56 78 9a bc de f0 00 00 00 00 00 CA FE BA BE FF EE DD CC ...
    |---First field------------------------| |---Second field------------|

    I have to seek to specified position then write it if I was using QDataStream. I want to simply assign a value to the structure member. Maybe the QDataStream is not suit for my situation.

  • You can use @QByteArray::append(const char*, int)@ and @QByteArray::fromRawData(const char*, int)@

    Be careful with this methods and take a look to Jeroentje@home's post.

Log in to reply