We help IT Professionals succeed at work.

Tcp/IP communication-member alignment-packing

barzangy
barzangy asked
on
The message format in my tcp/ip protocol are streams of packed structures. Like the following:

typedef struct _message {
    uint8_t node;
    int8_t ownerlevel;
    int32_t timeout;
} PACKSTRUCT _message;

here node is 1 byte, ownerlevel is 1 byte and timeout is  4 bytes.
So I receive 6 bytes in the InputStream. How can I typecast these 6 bytes to such a structure in Java?

This structure is packed in memory. i.e. there are no holes between them in the memory of the server.

The server is written in c++ and uses the following code to send the message:


_message * m = new _message;
m->node = 4;
m->ownerlevel = -7;
m->timeout = 1000;
m->timeout = htonl(m->timeout);
char * p = (char *) m;
send(socket1, p, sizeof(_message), 0);

How can I receive and typecast such a message form a java Socket?
Comment
Watch Question

Commented:
I would suggest you read the 6 bytes using a byte array (see java.io.InputStream for details).
Then instantiate a class with the values:

public class PACKSTRUCT_message
  {
    public byte node;
    etc ...
  }
...
PACKSTRUCT_message M=new PACKSTRUCT_message();
M.node= ... ;
etc ...

Please be careful in the order of the bytes in the timeout variable (it depends on the platform of the server).
For better programming, you can declare a contructor that take the values and initializes the members, and add readers for these members.

hope it helps :-)

Author

Commented:
Vbremaud:
But I want to write code which is not platform dependant that's why I choose Java. Also I may write this in an Applet. I thought of your suggestion before but It's clumsy and platform dependant. The endianity has to be corrected by using "ntohl" and "htonl".

Author

Commented:
the PACKSTRUCT is a macro and is telling the compiler to set 1 byte alignment between the elements of the structure. I.E. no holes.
CERTIFIED EXPERT

Commented:
Since you are using htonl, you know the endianness of the 32-bit variable (network byte order is BE).

Assuming you've read into a byte array of length 6,

byte[] buf = new byte[6];
int timeout = (((int)buf[2] & 0xFF) << 24
               | ((int)buf[3] & 0xFF) << 16
               | ((int)buf[4] & 0xFF) << 8
               | ((int)buf[5] & 0xFF));

Not pretty, but java doesn't really have facilities that cater to bit-stuffing.

Author

Commented:
I can also do the following:

Socket client = new Socket(host, port);

byte node = client.readByte();
byte ownerlevel = client.readByte();
int timeout = client.readInt();

There is also a readChar which reads two bytes.

By the way do I need to uses ntohl after reading an integer of 4 bytes?
CERTIFIED EXPERT

Commented:
What Socket are you using that provides "readInt" and "readByte"?

Author

Commented:
java.net.Socket in JBuilder 5.0

Author

Commented:
Sorry,
I actually get the InputStream and then do a readInt of the stream:

client = new Socket(host, port);
InputStream is = client.getInpuStream();
int timeout = is.readInt();

...etc
CERTIFIED EXPERT
Commented:
Looks like a DataInputStream.  According to the contract for readInt on that interface, that will work in place of the bit shifting I supplied (it actually performs the same operation).  So no, you don't have to do any sort of ntohl on the java side.

Since network byte order is big endian, and you use htonl before sending the value, readInt will do the right thing.  The first byte is left shifted the most (big endian means the most significant byte comes first).

Commented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

- Points for stimpyjcat

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Venabili
EE Cleanup Volunteer

Explore More ContentExplore courses, solutions, and other research materials related to this topic.