views:

150

answers:

2

In my program I have a few structs and a char array that I want to send as a single entity over UDP.

I am struggling to think of a good way to do this.

My first thought was to create a structure which contains everything I want to send but it would be of the wrong type for using sendto()

How would I store the two structs and a char array in another array so that it will be received in the way I intended?

Thanks

+5  A: 

Since C allows you to cast to your heart's content, there's no such thing as a wrong type for sendto(). You simply cast the address of your struct to a void * and pass that as the argument to sendto().

However, a lot of people will impress on you that it's not advisable to send structs this way in the first place:

  • If the programs on either side of the connection are compiled by different compilers or in different environments, chances are your structs will not have the same packing.

  • If the two hosts involved in the transfer don't have the same endinanness, part of your data will end up backwards.

  • If the host architectures differ (e.g. 32 bit vs. 64 bits) then sizes of structs may be off as well. Certainly there will be size discrepancies if the sizes of your basic data types (int, char, long, double, etc.) differ.

So... Please take the advice of the first paragraph only if you're sure your two hosts are identical twins, or close enough to it.

In other cases, consider converting your data to some kind of neutral text representation, which could be XML but doesn't need to be anything that complicated. Strings are sent as a sequence of bytes, and there's much less that can go wrong. Since you control the format, you should be able to parse that stuff with little trouble on the receiving side.

Update

You mention that you're transferring mostly bit fields. That means that your data essentially consists of a bunch of integers, all of them less than (I'm assuming) 32 bits.

My suggestion for a "clean" solution, therefore, would be to write a function to unpack all those bit fields, and to ship the whole works as an array of (perhaps unsigned) integers. Assuming that sizeof(int) is the same across machines, htons() will work successfully on the elements (each individually!) of those arrays, and you can then wrap them back into a structure on the other side.

Carl Smotricz
Thanks for the advice, the structs I have already defined purely contain bit fields and I am using htons() on the contents when ever there is more then 1 bit in the field. Will this negate the structs having different packing or should I still be concerned about this? Thanks
Darrel
No, `htons()` solves a related problem, but can't help you with packing and such. However: Updated suggestion coming up in my answer, just a minute...
Carl Smotricz
So if I were to write the function will the order of the bits in the structure be preserved? Or will there be extra bits between elements of the array to fill up the 32 bits I have for an int. Would packing 16 1 bit fields into a short unsigned int be a good way to maintain the bit structure? I assume shifting left would be the way to go about this?
Darrel
Well, turning all your bit fields into ints is indeed space-wasteful as you guessed, but it's simple. Are you worried about the amount of bandwidth you'll be using? If so, some bit-twiddling may be required. I would be much too lazy to go to all that trouble, though.
Carl Smotricz
I'm going away for some hours. If you want to pursue this further, someone else will have to help you, sorry. Maybe you'd like to post another question that more closely zeroes in on the specifics?
Carl Smotricz
Thanks for the help, I am a few bit shifts away from finishing a function to package the bits into an array nicely :)
Darrel
A: 

You can send multiple pieces of data as one with writev. Just create the array of struct iovec that it needs, with one element for each data structure you want to send.

John Zwinck