Bit-byte order.
Anyone know a good way off-hand to determine if a system is
[least/most] significant [byte/bit] first?
I''m working doing some networking stuff, and need to be able to make the client and server aware of the bit/byte order of each other so they can correctly build binary packets to send back and forth.
So far, the only good way I''ve found is to have the pair negotiate by sending specific bit patterns to each other until they find the corrent combination. It works fine, but it does seem to be a bit annoying to have every session start with
"Negotiating packet format...".
Any suggestions? Possibly you can get the information simply by some kind of function call on the socket I''m not aware of...
Ciao!
Check the htons(), htonl(), ntohs() and ntohl() macros/functions.
Network byte order is big-endian (most significant byte first).
The inner bit layout is not significant.
Network byte order is big-endian (most significant byte first).
The inner bit layout is not significant.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
*coughs slightly* Um...I was under the impression that those were only any significance for network address structures.
If you want to send a whole stack of binary data across, htonl, etc aren''t really that much use. ...I think.
*thinks* I guess you could try to split your data up into 16-bit packets and using htons and ntohs to convert it...maybe. You''d still have to worry about byte ordering...
Unless you send data via plain text (which, incidentally, I could have done, but chose not to, as a design decision), you have to worry about the server-client bit orders. At least three very respectable books have told me this, and I''m inclined to trust them, unless you care to elaborate.
If you want to send a whole stack of binary data across, htonl, etc aren''t really that much use. ...I think.
*thinks* I guess you could try to split your data up into 16-bit packets and using htons and ntohs to convert it...maybe. You''d still have to worry about byte ordering...
Unless you send data via plain text (which, incidentally, I could have done, but chose not to, as a design decision), you have to worry about the server-client bit orders. At least three very respectable books have told me this, and I''m inclined to trust them, unless you care to elaborate.
Since bytes are seen as an atomic thing in all computers, the order that bits are stored is irrelevant to anything you''ll ever do. There is no way to know which way the bits are stored in a byte.
When sending large amounts of binary data, you''re still going to have to re-order the bytes anyway, so you may as well do it using htonl() and ntohl().
Or, you know what the most common system is and write your own version of htonl() et al to accodidate these systems. For example, if 90% or your hosts are intel machines, which use little-endian order, it may be a waste to convert to big-endian to send over the network and then back to little-endian again on the receiving end.
codeka.com - Just click it.
When sending large amounts of binary data, you''re still going to have to re-order the bytes anyway, so you may as well do it using htonl() and ntohl().
Or, you know what the most common system is and write your own version of htonl() et al to accodidate these systems. For example, if 90% or your hosts are intel machines, which use little-endian order, it may be a waste to convert to big-endian to send over the network and then back to little-endian again on the receiving end.
codeka.com - Just click it.
> Since bytes are seen as an atomic thing in all computers, the
> order that bits are stored is irrelevant to anything you''ll ever
> do. There is no way to know which way the bits are stored in a
> byte.
*frowns* Rubbish. All you need to do is play with XLib for a little while and you''ll find the pixels / tuples (sp?) depend significantly on what the server''s bit/byte order is. That''s why the ImageByteOrder and BitmapBitOrder are defined.
In this case, it is relevant. If I send an 8-bit value in MSB which is 10000011 (ie. -3) and an LSB system recieves it, it''ll intepret it as -(1*2^0 + 1*2^6). Assuming the bit length of the value sent is even the same on the two systems.
>When sending large amounts of binary data, you''re still going to
>have to re-order the bytes anyway, so you may as well do it using
>htonl() and ntohl().
So you''re suggesting I go:
struct Blah { lots of stuff }
Function x
{
struct Blah *k;
unit16_t *array;
int size, i;
k = (struct Blah *) malloc(sizeof(struct Blah));
/* Init k */
array = (uint16_t *) k;
size = sizeof(struct Blah)/sizeof(uint16_t);
/* Hope to god its an integer division of 16 bits */
for (i = 0; i < size; ++i)
{
array = htons (array);<br> }<br><br> write (socketfd, (void *)array, size * sizeof (unit16_t));<br> …<br>}<br><br>and on the other side, recieve the whole pile of data, run<br>ntohs on every segment, and then cast it back into a structure<br>block? <br><br>What if the structure block padding is different on the various implementations (ie. bytes defining this as a structure)? <br><br>What if the component element type definitions of the structure are different lengths on server and client?<br><br>Why the heck did sun both with the RPC spec if its such an easy thing to do? =P<br>I''ve decided to go for self defined binary packets. I building them using (void *) alloc (X) to create the data segments and<br>data | 1 | 4 | 8 | etc. to set the bit patterns. Once the server and client have established if they are LSB or MSB, packets sent to the other are created differently. They are created using the other associated number pair (ie. 2^0 is now 2^7, 2^2 is now 2^5, etc.).<br><br>It''s all cool. I know some people dont like to do it this way, but I''ve decided to. <br><br>-All I want to know is- : How to determine the bit/byte order. Is it possible by some function call?<br><br>DONT tell me the bit order is insignificant, stupid or not worth bothering to think about. All I want to know is, how the heck do you figure it out. For example, in Unix Network Programming (stevens) they use the following to determine the byte order:<br><br>int main (int argc, char **argv)<br>{<br>union { short s; char c[sizeof(short)]; } un;<br>un.s = 0x0102;<br>printf ("%s: ", CPU_VENDOR_OS);<br>if (sizeof(short) == 2) <br>{<br>if (un.c[0] == 1 && un.c[1] == 2)<br> printf ("big-endian\n");<br>else if (un.c[0] == 2 && un.c[1] ==1) <br> printf ("little endian\n");<br>else<br> printf ("Unknown"<br>}<br>else<br> printf ("Sizeof(short) = %d\n", sizeof(short));<br><br>exit (0);<br>}<br><br>Which apparently does what I want. However, I''m not familiar with the union construct, which makes me not understand the fragment; and I''m naturally wary of using a code fragment I don''t understand completely (will it always work? *shrugs*).<br><br>Later.<br> </i>
> order that bits are stored is irrelevant to anything you''ll ever
> do. There is no way to know which way the bits are stored in a
> byte.
*frowns* Rubbish. All you need to do is play with XLib for a little while and you''ll find the pixels / tuples (sp?) depend significantly on what the server''s bit/byte order is. That''s why the ImageByteOrder and BitmapBitOrder are defined.
In this case, it is relevant. If I send an 8-bit value in MSB which is 10000011 (ie. -3) and an LSB system recieves it, it''ll intepret it as -(1*2^0 + 1*2^6). Assuming the bit length of the value sent is even the same on the two systems.
>When sending large amounts of binary data, you''re still going to
>have to re-order the bytes anyway, so you may as well do it using
>htonl() and ntohl().
So you''re suggesting I go:
struct Blah { lots of stuff }
Function x
{
struct Blah *k;
unit16_t *array;
int size, i;
k = (struct Blah *) malloc(sizeof(struct Blah));
/* Init k */
array = (uint16_t *) k;
size = sizeof(struct Blah)/sizeof(uint16_t);
/* Hope to god its an integer division of 16 bits */
for (i = 0; i < size; ++i)
{
array = htons (array);<br> }<br><br> write (socketfd, (void *)array, size * sizeof (unit16_t));<br> …<br>}<br><br>and on the other side, recieve the whole pile of data, run<br>ntohs on every segment, and then cast it back into a structure<br>block? <br><br>What if the structure block padding is different on the various implementations (ie. bytes defining this as a structure)? <br><br>What if the component element type definitions of the structure are different lengths on server and client?<br><br>Why the heck did sun both with the RPC spec if its such an easy thing to do? =P<br>I''ve decided to go for self defined binary packets. I building them using (void *) alloc (X) to create the data segments and<br>data | 1 | 4 | 8 | etc. to set the bit patterns. Once the server and client have established if they are LSB or MSB, packets sent to the other are created differently. They are created using the other associated number pair (ie. 2^0 is now 2^7, 2^2 is now 2^5, etc.).<br><br>It''s all cool. I know some people dont like to do it this way, but I''ve decided to. <br><br>-All I want to know is- : How to determine the bit/byte order. Is it possible by some function call?<br><br>DONT tell me the bit order is insignificant, stupid or not worth bothering to think about. All I want to know is, how the heck do you figure it out. For example, in Unix Network Programming (stevens) they use the following to determine the byte order:<br><br>int main (int argc, char **argv)<br>{<br>union { short s; char c[sizeof(short)]; } un;<br>un.s = 0x0102;<br>printf ("%s: ", CPU_VENDOR_OS);<br>if (sizeof(short) == 2) <br>{<br>if (un.c[0] == 1 && un.c[1] == 2)<br> printf ("big-endian\n");<br>else if (un.c[0] == 2 && un.c[1] ==1) <br> printf ("little endian\n");<br>else<br> printf ("Unknown"<br>}<br>else<br> printf ("Sizeof(short) = %d\n", sizeof(short));<br><br>exit (0);<br>}<br><br>Which apparently does what I want. However, I''m not familiar with the union construct, which makes me not understand the fragment; and I''m naturally wary of using a code fragment I don''t understand completely (will it always work? *shrugs*).<br><br>Later.<br> </i>
quote: Original post by Shadow Mint
> Since bytes are seen as an atomic thing in all computers, the
> order that bits are stored is irrelevant to anything you''ll ever
> do. There is no way to know which way the bits are stored in a
> byte.
*frowns* Rubbish. All you need to do is play with XLib for a little while and you''ll find the pixels / tuples (sp?) depend significantly on what the server''s bit/byte order is. That''s why the ImageByteOrder and BitmapBitOrder are defined.
No, that''s because you can have RGB pixel ordering or BGR. This has nothing to do with how the computer represents bits internally. All bit operations like shifting and masking are done on a conceptual level. If not, a left shift would do different things depending on the "endian-ness" of the bits. That is, if the computer stored bits in big-endian order, a left shift would multiply, but if it stored them in little-endian order, a left shift would divide.
You can''t do it the way you suggested because you need to it on a per-value basis, if you get my meaning. For example:
struct MyData{ short s; int i; byte b;};void DoSend( MyData *val ){ MyData data; data.s = htons( val->s ); data.i = htonl( val->i ); data.b = htonb( val->b ); send( sock, &data, sizeof(MyData), 0 );}
If all the data items are the same size, it''s OK to do it in a loop. If not, you have to do it "manually".
When you send a struct over the network, you usually force the padding to 0 so a) you don''t have to worry about adjusting it on the other end and b) you may have a few less bytes to send.
Anyway, there''s no library function that I know of that will tell you the bit order. That union code you gave will work. Basically a union is like a struct, but all members share the same memory. So:
union A{ int i; short s[2]; byte b[4];};void main(){ A u; if( (&u.i == &u.s) && (&u.s == &u.b) ) cout << "same" << endl; else cout << "different" << endl;}
The output of that would be "same". Also, sizeof(A) would be 4.
codeka.com - Just click it.
Well if mylong == htonl(mylong), where long is some asymetrical pattern then you are on a big-endian machine.
I though it was obvious you could use these functions for that.
I though it was obvious you could use these functions for that.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
quote: Original post by Fruny
Well if mylong == htonl(mylong), where long is some asymetrical pattern then you are on a big-endian machine.
I though it was obvious you could use these functions for that.
Duh, of course How silly of me...
codeka.com - Just click it.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement