0

I wanted to know what byte sorting method my PC uses. So I experimented to see if any u_long variable remains the same after it is converted to the htons() function.

u_long example = 0x12345678;
printf("#%x -> #%x -> #%x\n",  example, htonl(example), htonl(htonl(example)));

During the test, I called the htons function once more, and once again, I found that the htons applied function changed the value again.

Output

#12345678 -> #78563412 -> #12345678

Expected

#12345678 -> #78563412 -> #78563412

The htons function sorts all the data into big endian, Why does the data change when called again? What's the problem? Please let me know my mistake.

MeoH
  • 13
  • 4
  • 6
    How on earth do you expect `htons` to "know" the value you're provided isn't in host-order? It's in the name. The `h` means `host`. It takes whatever native representation is (big or little endian) as host-order, and orders it as-network (big endian). If you feed it the same value again, it assumes you're once again, providing a value in host-order and will, again, do network-order. (and of course, all of this is a giant no-op when you're host is already in network-order). In short, there is no "problem". `htons` is doing *exactly* what you asked of it. – WhozCraig Sep 14 '22 at 03:10
  • "Big endian" does not mean that "highest **value** bytes" are always put on the left. Try it with a value like `0xFF000000` and examine the results. Yes, calling the function again and again **will** keep reversing the sequence (if you are on that kind of architecture). – Fe2O3 Sep 14 '22 at 04:19
  • 1
    `The htons function sorts all the data` That's the first mistake. It doesn't sort anything. – n. m. could be an AI Sep 14 '22 at 04:59

1 Answers1

3

htonl takes a long, expecting host byte order, and converts it to network byte order. On a host where the host byte order is opposite the network byte order, it swaps the bytes. Calling it again will just swap the bytes again. There's no sorting involved, just swapping.

When you call htonl with a parameter of htonl(0x12345678), it has no way of knowing that this sequence of four bytes means 0x12345678 in network byte order. For all it knows, the input could literally be the integer 0x78563412 expressed in host byte order. It simply does the swap as designed and documented, expecting its input in host order and emitting an output in network byte order.

If you subvert its documented expectations, you are not guaranteed a meaningful result, just like if you e.g. passed a pointer to free that did not come from malloc.

nanofarad
  • 40,330
  • 4
  • 86
  • 117
  • Then can't I know the byte sorting method of my CPU by repeatedly calling htons? – MeoH Sep 14 '22 at 03:21
  • 2
    @MeoH You can know the order by supplying `htonl()` with a known value like `0x12345678` and examining the result. – chux - Reinstate Monica Sep 14 '22 at 03:35
  • Sure you can, @MeOH. You know (or can / should know) that network byte order is from most-significant byte to least. If you feed `htonl()` a `uint32_t` input whose bytes all have different values then the result tells you unequivocally how your host's byte order maps to big-endian order. Is that not in fact the experiment you were trying to perform? What additional information do you think you would have gleaned if the result of the program were what you expected? – John Bollinger Sep 14 '22 at 03:35
  • @MeoH Is there a reason that you keep referring to it as byte sorting rather than byte ordering? There is no sorting involved. – Avi Berger Sep 14 '22 at 03:38
  • https://stackoverflow.com/questions/4181951/how-to-check-whether-a-system-is-big-endian-or-little-endian I'm reading the code for this link, but why do I have to use char*? Why doesn't it work if I use a different data type? Shouldn't it be solved by using data types smaller than int such as short? – MeoH Sep 14 '22 at 04:46
  • @MeoH I don't see how that link is related. htonl *unconditionally* swaps on certain CPU architectures because the library authors know *a priori* that the network order doesn't match the host order there. It *unconditionally* returns the value as-is on others, because the library authors know that the host order already matches network order. It is infeasible to explain how a different answer to a different question works in the space of a comment. – nanofarad Sep 14 '22 at 13:41