>Jinghou Li <jli> writes:
>>I am writing a program that needs to send arbitrary type of data via BSD
>>socket.
>>Right now, I am using a char array to buffer those data. In my implementation
>>one thing is guaranteed: both the sending and receiving ends know what type of
>>data it's supposed to write/read. So, I am worrying about how to convert
>>any type of data into char string and the reverse. The solution should be
>>portable as all kinds fo UNIXs are supposed to run this program.
>>Any suggestion? Please help!
>>- Jing-Hou Li
>You don't have to worry about converting different types of data into character
>strings. You only need ensure that you convert integers and longs to network
>byte order before being transmitted and back to host order upon reception (or
>before using). A template of sorts to lay over the buffer that would define
>the data would make life alot easier. Else you'd have to worry about the num-
>ber of bytes wide a particular data was and caculate your own offsets. In a
>nutshell you plug the data in and let the underlying hardware figure out how
>to break it apart byte-by-byte.
>struct template {
> int something;
> long youpick;
> struct gluttonforpunishment {
> char string[104];
> int whatever;
> }
;
>} *tptr;
This is just plain wrong.
You cannot be sure what size the integer types are.
And even you you have two machines with compilers where integer type sizes
match, alignment differences of the compilers can make the memory layout
different. E.g. assume that int is 16 bit and long is 32. Then on a machine
with long alignment <= 2, youpick has offset 2, while on machines with long
alignment 4, youpick has offset 4 .
Portable to a wider range of machines is:
struct template {
int something:16;
int pad:16;
int youpick:32;
struct gluttonforpunishment {
char string[104];
int whatever:16;
};
Quote:} *tptr;
or /* of course you have to be consistent with your pick */
struct template {
int youpick:32;
int something:16;
struct gluttonforpunishment {
char string[104];
int whatever:16;
};
Quote:} *tptr;
However, keep in mind that there is no guarantee that the compiler will
actually place all members with the desired sizes in the desired order.
It is safer to disassemble / assemble integers to/from single chars.
This way, you can broaden the portability to all systems that have >= 8 bit
chars, BSD style sockets and transmit 8 bit/char on sockets.
( It may be argued that sockets no longer have
BSD style if you transfer anything but 8 bits/char )
Sort of a tradeoff between the degree of unportability and unmaintability :-)
If you have some CPU cycles to burn, you can write your own portable XDR
library (to overcome the problem that not all machines have XDR) and use
that.
Joern Rennecke