When calling htons()
on 1
and inspecting the bytes of the output, my (naive) inspection method below appears to show that the output takes the form 0x0100
.
I am confident that htons()
is doing what it should, but can anyone explain the misleading behavior from the code written? i.e. is there a subtle bug with the interpretation of the result of htons()
?
#include <cstdint>
#include <iostream>
#include <arpa/inet.h>
int main() {
uint16_t port = 1;
uint16_t big_endian_port = htons(port);
std::cout << "First byte: " << ((big_endian_port >> 8) & 0xff) << std::endl;
std::cout << "Second byte: " << (big_endian_port & 0xff) << std::endl;
}
Godbolt (Execution Result): https://godbolt.org/z/d55ne3M9G
Solt's answer provides a very practical answer and shows how to deal with the results as a byte sequence. For the records, here some more explanations about the surprise regarding the output of your code.
htons()
converts from machine specific byte ordering to network byte ordering, which appears to be most significant byte first, aka big endian.
If you're on a big endian machine, 1 would be stored on two consecutive bytes 0x00 and 0x01. The result of the function would be 0x00 0x01 since there is no change in byte ordering. And if you print the result, you'd still get 1.
But you work one a little endian machine: 1 is stored 0x01 (the least significant part first) followed by 0x00 (the most significant part, i.e leading zeros). The result of the function would be 0x00 0x01 with the reverse ordering.
All this works as designed
However, on a little endian machine (your case), when you deal with the result not as a byte sequence but as a number, your machine would interpret it as a number like any other and understand the first byte 0x00 as the least significant part and the second byte 0x01 as the most significant, i. e. 0x0100. So your code, which works on a number, would then show this result as right shifting works on the whole number.
Not related: Fortunately, writing to a socket with send() takes the buffer according to the byte ordering, i.e. byte by byte. So in your case 0x00 followed by 0x01 as intended. When you then receive the data on the target host, calling use ntohs() will make sure that the byte ordering used during the communication is transformed according to the endianness of the receiving host.