Reputation: 3
I'm working on a code where I have a struct with one of it's members is a dynamic array (size unknown until runtime). I need to send this struct over a UDP connection and be able to read and process the data on the other end.
I know I can use a pointer and malloc to define a dynamic array but I can't send the pointer over UDP. and I'm trying to avoid serialization as well.
the struct is something like this where user has to enter ID to define message type as well as the message in the array.
struct foo
{
unsigned int ID;
unsigned int Num;
unsigned int size;
char arr[size]; //I know this is not acceptable in C, just typing to show my question.
};
Is there another method to create a dynamic array that can be sent over UDP socket? and what is the best way to handle this on the receiving party as well?
Upvotes: 0
Views: 1546
Reputation: 9855
You could define a structure that has a minimal array and allocate memory for a structure with a bigger array.
The following code example is not valid C, it is incomplete. It also doesn't handle possible byte order or size differences of the int
values when sent over the network to a different machine.
struct foo
{
unsigned int ID;
unsigned int Num;
unsigned int size;
char arr[1];
};
int size = 123;
int i;
int ret;
struct foo *ptr = malloc(offsetof(struct foo, arr) + size);
ptr->ID = 42;
ptr->Num = 99;
ptr->size = size;
for(i=0; i<ptr->size; i++)
{
ptr->arr[i] = data;
}
ret = sendto(sockfd, ptr, offsetof(struct foo, arr) + size, flags,
dest_addr, addrlen);
The compiler doesn't care that you access an array index bigger than what you defined in the structure declaration. You have to check the index in your code to avoid memory access errors.
The receiver can use recvfrom()
with MSG_PEEK
and the size of the header (offsetof(struct foo, arr)
) into a temporary structure struct foo tmp;
first, next allocate memory according to the size
field, then read the full size of the structure into the dynamically allocated memory. See also How to read UDP packet with variable length in C
Or use a fixed buffer of the maximum size for recvfrom()
, then copy the data to a dynamically allocated structure. The return value of recvfrom()
will tell you the necessary size.
Edit according to suggestions in Matthias Simon's answer:
If your compiler supports zero-sized arrays the code can be simplified a bit.
In the structure definition you can use char arr[0];
instead of char arr[1];
. This allows to use sizeof struct foo
instead of offsetof(struct foo, arr)
in malloc()
, sendto()
and in recvfrom()
with MSG_PEEK
.
Upvotes: 1
Reputation: 69
There's nothing special about sending structs with dynamic size over UDP. Generally you just have to allocate enough memory, like Bodo described in his answer. Also, have a look at the GCC manual: Arrays of Length Zero and Arrays of Variable Length, I hope this helps. And don't forget that UDP messages have a size limit.
[...] I'm trying to avoid serialization as well.
I regularly see people avoiding codecs, because they aim for good performance. In the end they get the opposite, because of endianess swapping and packing issues. Serialization is your friend, especially when communicating with other processes. Worth reading is Rob Pike's article about byte-order
Upvotes: 2