1

I have a c++ socket program where there are two processes. The server process and client process. The client registers with the server and listens on a port for any message from server.

I have defined a "char *buffer" which will have my message. The message size is say 59000 Bytes. Now before transmitting the message i am adding the message size at the beginning of the buffer,

size=htonl(59000)
Buffer= size + <Actual Message>

so that client process when ever it gets a message it reads first two bytes to get size first, knows the size of message transmitted and then it reads the complete message from the socket. This is done as below

59000 in binary format is          00000000 00000000 11100110 01111000  
htonl(59000) in binary format is   01111000 11100110 00000000 00000000

I used memcpy to copy this size to charcter buffer.

memcpy(buffer, &size, 4) <since size of int is 4>

After transmitting the message at client when i read the first two bytes i get the size as zero. But if i read the next two bytes i get the correct size that is 59000. The way i am reading the message size at client is as mentioned below

int messageSize=0;
memcpy(&messageSize, buffer, 2 );

Can some one please explain me why the message size is stored in the second two bytes and not in the first two bytes.

I would be very grateful to you if you can help me. I have been trying to understand this from quite some time.

6
  • Maybe you should send the whole int. Commented Mar 25, 2015 at 4:14
  • I like your style of explaining. However, I still need to see the actual source code, or I can't spot the bug. Sorry. Just paste it and surround it with <code> tags or just indent it four spaces. Commented Mar 25, 2015 at 4:16
  • Or, lol you could do what the other commenter said. What is sizeof(int)? Commented Mar 25, 2015 at 4:17
  • You actually memcpy four bytes when preparing to send - so seem to know how many bytes htonl returns - but you talk about reading just 2 bytes....! Commented Mar 25, 2015 at 4:36
  • Why do you care about individual bytes and two-byte chunks? You have ints. Work with ints and sizeof(int)-sized chunks (don't use 4 or 2 or whatever, use sizeof(yourtype)). Commented Mar 25, 2015 at 7:08

2 Answers 2

1

There is one serious mistake in your explanation :

59000 in binary format is          00000000 00000000 11100110 01111000  
htonl(59000) in binary format is   01111000 11100110 00000000 00000000

is wrong it really is the ohter way around so

59000 in binary format is          01111000 11100110 00000000 00000000
htonl(59000) in binary format is   00000000 00000000 11100110 01111000  

that is this is the case on cpu that is little endian. So since a int is 4 bytes, this perfectly explains why you receive 2 zero bytes first.

htonl stands for host to network long. host order is the ordering of the bytes on the host. This can be different on little and big endian machines, but network order is well defined and it must be because otherwise computers could not talk to eachother.

There is also htons: for short and the reverse of htons and htonl is ntohl and ntohs

These functions do the exact same thing as their counterparts, that is in a big endian system they don't do anything at all, in little endian they reverse the byte order of whatever comes in. htons(htons(x)) does nothing. There is no way to detect for the computer if a value is byte reversed. use ntohl and ntohs when coming from network order to host order, you'll need this at the client when you receive the first 4 bytes and want to know the length.

Sign up to request clarification or add additional context in comments.

Comments

0

htonl converts a long (meaning 4-byte int) from host-byte-order to network-byte-order. Network-byte-order is defined as big-endian, that is the most significant byte of a multi-byte number is first. The host-byte-order is either big-endian (in which case htonl does nothing) or little-endian (in which case htonl reverses the bytes).

In all cases, the bytes representing 59000 will be transmitted as 0x00 0x00 0xe6 0x78. So if you only read the first two bytes, you will always get 0x00 0x00. To read the value correctly on all systems, you need to read all four bytes into a 32-bit integer, and then call ntohl to convert the number from network-byte-order to host-byte-order.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.