Subi Suresh
Subi Suresh

Reputation: 301

Why is data sent across the network converted to network byte order?

I'm not sure how to use hton(). The theory is that any data sent over the network should be in network byte (i.e. big-endian) format. Suppose client A supports big-endian and B supports little-endian. I'm sending data from A to B and the data is read as multibyte. Then in the network we need to convert data to network byte order using htonl() and htons(). Since client A is already big-endian, htonl() and htons() return the same output. But B is little-endian, so those functions reverse the order. Given that, how can we say that adhering to a common format (i.e. big-endian) is a solution to the problem when big- and little-endian machines need to communicate?

Upvotes: 3

Views: 4149

Answers (2)

glglgl
glglgl

Reputation: 91017

I'll try it the other way, showing the whole flow:

Sending 0x44332211 over the wire always happens as 44 33 22 11. The sender's htonl() ensures that, either by reverting the order of the bytes (on LE machines) or by just leaving them the way they are (on BE machines). The receiver turns the 44 33 22 11 into 0x44332211 with ntohl() - again, either by reverting them or leaving them.

The mentionned functions {hton,ntoh}{l,s}() help programming in a portable way: no matter if the program tuns on a LE or BE machine, they always work the way they should. Thus, even on BE machines the functions should be called, even if they are noops.

Example:

A (BE) wants to send 0x44332211 to B (LE).

  1. A has the number 0x44332211 in memory as 44 33 22 11.
  2. A calls htonl() as the program has been written to be portable.
  3. The number is still represented as 44 33 22 11 and sent over the wire.
  4. B receives 44 33 22 11 and puts it through ntohl().
  5. B gets the value represented by 11 22 33 44 from ntohl() and puts it into the respective variable - which then results to 0x44332211 as wanted.

Again, the need for always calling these function saves you from thinking about which kind of machine you are programming for - just program for all kinds of machines and call each of these function when they are needed.

The same example can be expressed without knowing if A or B are BE or LE:

  1. A has the number 0x44332211 in memory.
  2. A calls htonl() so that the number is sent as 44 33 22 11 over the wire. Whether this is done by reverting or by leaving it is determined by the endianness of host B.
  3. B receives 44 33 22 11 and puts it through ntohl(). This one reverses it or not, depending on the endianness of host B.
  4. B gets the value 0x44332211 as wanted.

Upvotes: 7

Michael Mrozek
Michael Mrozek

Reputation: 175355

I think you're thinking that client B seeing the bytes in "reversed order" means that they're wrong. The bytes will be in reverse order compared to client A, but that's because client A interprets integers backwards from client B; both will still interpret it as the same number in the end. For example, one machine would represent the number 4 as 00 00 00 04. The other would represent it as 04 00 00 00, but both would still see it as a 4 -- if you add 1 to it you're going to get 00 00 00 05 and 05 00 00 00, respectively. The hton/ntoh functions exist because there's no way to look at a number and know if it's big- or little-endian, so the receiver can't be sure which way to interpret the bytes

Upvotes: 1

Related Questions