views:

97

answers:

3

Hi

I have a header field of 2 bytes where first four bits are packet type and other 12 bits are for length. but i don't know how to store this values and retrieve them.

I am using ms c++ for client and java for server. It is the client which has to set this values and server has to retrieve it.

Thanks

+4  A: 

Storing

unsigned short get_header(unsigned char type, unsigned short length)
{
  return (static_cast<unsigned short>(type) << 12) | length;    
}

Retrieving (from unsigned short)

unsigned short header = /* get 2 header bytes */
unsigned char type = header >> 12;
unsigned short length = header & 0xFFF;

Retrieving (from unsigned char[2])

unsigned char bytes[2] = /* get 2 header bytes */
unsigned char type = bytes[0] >> 4;
unsigned short length = bytes[0] & 0xF | bytes[1];
Peter Alexander
I would use an unsigned short to avoid problems from sign-extension.
Software Monkey
Good point, will change now.
Peter Alexander
rsp
+1 but remember that if your client and server could run on different endian hardware, be very careful about byte order because the bit masking could pull off different bits on each end.
Mark B
I was under the impression that endianness was hidden in C++?
Peter Alexander
Endianness is hidden except when casting a pointer to a type of a different size. For instance, unsigned short x; unsigned char* px = (unsigned char*) On a little endian machine, px[0] will be bits 7 through 0 and px[1] will be bits 15 through 8 where 0 is the lsb. I think your example is fine, but you would probably have to worry about endianness when writing the code for \\*get 2 header bytes*\
Jason
+1  A: 

You must use the numeric AND operation and right-shift to extract the values.

Your header:     TTTTLLLLLLLLLLLL
Mask for type:   1111000000000000 = 0xF000
Mask for length: 0000111111111111 = 0x0FFF

Extracting:

// Just an example, this is 0001001000110100 in binary
uint16_t exampleHeader = 0x1234;

// Mask out the length and shift type to the right to get 0001 (binary)
uint8_t type = (exampleHeader & 0xF000) >> 12;

// Same here but no shift needed, returns 001000110100 (binary)
uint16_t length = exampleHeader & 0x0FFF;

Assembling a header:

uint16_t header = (type << 12) | length;

You can replace the integer types (uintXX_t) with the corresponding type of your language, like unsigned long. The code should be the same for Java and C++, except for the type keywords.

AndiDog
A: 

on the c/c++ size atleast, you could simply use this structure: don't know if you can do this in java tho...

struct Header{
   unsigned short
         type: 4
         length: 12
         ;
};  

note, those might need to be switched around

also, you might have endian problems, endian depends from processor type to processor type (all amd and intel processors that I know of are the same, the only ones that I know of that are different are PowerPC ones I think, most noteably used in the PS3 and xbox 360)

matt