How to send struct with array of varying length?

59 Views Asked by At

How to send struct with array of varying length? I use enet library and memcpy for serialization.

client:

struct data{
  enum type type;
  int* data;
};

int world[10];
for(int i =0;i<10;i++)
{
    world[i] = i;
}

struct data dt;
dt.data = malloc(sizeof(int)*10);
dt.type = 1;

for(int i =0;i<10;i++)
{
    dt.data[i] = i;
}

char msg[1024];

memcpy(msg, &dt, sizeof(dt));

ENetPacket *pack = enet_packet_create(msg, sizeof(msg)+1, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, pack);

server:

ENET_EVENT_TYPE_RECEIVE:
        
            struct data copy_data;
            copy_data.data = (int*)malloc(10*sizeof(int));

            memcpy(&copy_data, event.packet->data, sizeof(struct data));

            for(int i = 0;i<10;i++)
            {
                printf("%d", copy_data.data[i]);
            }

What I made wrong? And how to send struct with array of varying length right?

1

There are 1 best solutions below

0
Some programmer dude On

Turning my comment into an answer, using a flexible array member it might be done something like this:

struct data
{
    enum type type;
    uint32_t length;  // Use fixed-width type since other types can be of different lengths
    int32_t data[];   // The actual array of data
};

// ...

// Create data structure
uint32_t length = 10;  // Number of elements in the array
struct data *my_data = malloc(sizeof *my_data + length * sizeof(int32_t));
my_data->type = ...;  // Set the type
my_data->length = length;  // Number of elements in the array

// Fill the array with (dummy) data
for (uint32_t i = 0; i < my_data->length; ++i)
{
    my_data->data[i] = i;
}

// ...

// Now to send the data
size_t packet_size = sizeof(my_data) + (my_data->length * sizeof my_data->data[0]);
ENetPacket *pack = enet_packet_create(my_data, packet_size, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, pack);

There's no copying. There's no duplication of data. There's no worrying about extra pointers. And the array inside the structure can be used like it was any other array.


Now for the receiving of the structure, that will be trickier because you don't really know how much data you will be receiving.

You need to receive it in two parts: First the main structure, using a pointer to a struct data and read sizeof(struct data) bytes; Then the actual data, reading into my_received_data->data and my_received_data->length * sizeof my_received_data->data[0] bytes.

Also be careful if you're sending between systems with different endianness. You might need to do a byte-order swap of all the data on either side of the connection. Or specify that all packets are sent with a specific (network I suggest) byte order and always do a byte-order swap on both sides.