Search code examples
c++qttcp

QT TCP client sends data but netcat receives random values


I'm facing a silly and frustrating problem with a simple TCP client implemented in QT. Specifically, it is a console application where a socket is instantiated and then connected to a server (netcat) listening on loopback. What it sends does not correspond to what netcat receives. Moreover the result is non-deterministic (i.e. each time the data is different) The snippet of code is the following

#include <QCoreApplication>
#include <QDebug>
#include <QByteArray>
#include <QTcpSocket>

enum class Command: unsigned char {
    getNodeConnectionStatus = 0x00,
    getNodeHopCount,
    getNodesParent = 0x10
};

struct CommandHeader {
    Command command;
    size_t size;
} __attribute__((packed,aligned(1)));

struct Address {
    unsigned char value[24];
} __attribute__((packed,aligned(1)));

struct CommandPayload {
    struct Address address;
};

struct NodeHopCount: public CommandPayload
{
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTcpSocket socket;
    socket.connectToHost("localhost", 2500);

    CommandPacket p;
    p.header.command = Command::getNodeHopCount;
    p.header.size = 1;

    struct NodeHopCount payload;
    
    memset(payload.address.value, '\0', 24);
    memcpy(payload.address.value, "AA:BB:CC:DD:EE:FF:00:11", 23);

    p.payload = new unsigned char[sizeof(payload)];

    memset(p.payload, '\0', sizeof(payload));
    memcpy(reinterpret_cast<void *>(p.payload), reinterpret_cast<void *>(&payload), sizeof(payload));
    QByteArray bytes(reinterpret_cast<char *>(&p), sizeof(p.header) + sizeof(payload));

    socket.write(bytes);
    socket.flush();
    socket.close();
    return a.exec();
}

and this is the output of two consecutive runs

solux [bin]$ nc -l -p 2500 -x -vv
Listening on any address 2500 (rtsserv)
Connection from 127.0.0.1:36670
▒����l��]U Received 33 bytes from the socket
00000000  01 01 00 00  00 00 00 00  00 1A 81 86  C8 7F 00 00  ................
00000010  C0 6C ED 92  5D 55 00 00  01 00 00 00  00 00 00 00  .l..]U..........
00000020  20                                                                  
Total received bytes: 33
Total sent bytes: 0
solux [bin]$ nc -l -p 2500 -x -vv
Listening on any address 2500 (rtsserv)
Connection from 127.0.0.1:50468
▒a%�bp�U Received 33 bytes from the socket
00000000  01 01 00 00  00 00 00 00  00 1A 61 00  25 7F 00 00  ..........a.%...
00000010  C0 1C 62 70  AF 55 00 00  01 00 00 00  00 00 00 00  ..bp.U..........
00000020  20                                                                  
Total received bytes: 33
Total sent bytes: 0

It seems a pointer issue but I cannot spot the root cause. Can anyone help me?

UPDATE I had forgotten a piece This is the definition of CommandPacker, I'm so sorry Thank you to Igor Tandetnik

struct CommandPacket {
    struct CommandHeader header;
    unsigned char *payload;
};


Solution

  • This should work:

    QByteArray bytes(reinterpret_cast<char *>(&p), sizeof(p.header));
    bytes.append(reinterpret_cast<char *>(&payload), sizeof(payload));
    

    These two pieces of data are not one chunk. You must copy them separately! You could also just do 2 writes, instead of copying data to a single QByteArray.

    Finally, add checking for return values of IO functions!