0

I have a define like the following:

#define LOCALHOST            2130706433

I'm trying to correct the network/host bytes order when working with sockaddr_in:

struct sockaddr_in src;
src.sin_port = htons(0);
src.sin_family = AF_INET;
src.sin_addr.s_addr = htonl( LOCALHOST );

This seems to be ordering incorrectly as I'm seeing 1.0.0.127 if I print src.sin_addr.s_addr to stdout.

What's the right way of doing this?

randombits
  • 47,058
  • 76
  • 251
  • 433
  • Related? http://stackoverflow.com/questions/11423338/same-output-for-htonl-and-ntohl-on-an-integer – Fantastic Mr Fox Sep 12 '16 at 23:47
  • I have to question whoever wrote that LOCALHOST define. Using decimal instead of hexadecimal for that constant is simply *strange*. – Zan Lynx Sep 13 '16 at 00:00
  • htonl() (and others) are designed to properly "Convert multi-byte integer types from host byte order to network byte order". For every host. Regardless of the host order. For instance, if your host order matches net order, the macros generally do nothing. – 2785528 Sep 13 '16 at 00:04

3 Answers3

6

2130706433 in decimal is 0x7f000001 in hexadecimal, so this is already 127.0.0.1 in network byte order.

If you're using htonl() on an Intel x86 platform, since x86 is little-endian, htonl() ends up reversing the bits.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • In other words, why use `htonX` for data you don't intend to send over net and conversely `ntohX` for data you didn't receive from the net? – Adrian Colomitchi Sep 13 '16 at 00:09
4

Most platforms have a INADDR_LOOPBACK constant to present 127.0.0.1. You should use that constant instead of defining your own:

src.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

If your host order matches net order (or not), the macros generally do nothing (or all the right things).

In other words, where you apply the macros, is logically the same regardless of the host order.

The goal is portability. Using the macros all the time makes the code more portable, and relieves the programmer (or code reader) of needing to know the hosts order.


example: reporting a_hostname in both digi-dot form and in hex network order.

std::cout << "a_hostname '" << a_hostname << "' maps to " 
          << target_host_digi_dot
          << " (" << std::hex << std::setfill('0') 
          << ntohl(ret_addr.sin_addr.s_addr) << ")" 
          << std::endl;

Similar example -

// ////////////////////////////////////////////////////////////////
// returns previous sin_addr in Host Byte Order
// sets sockaddr_in.sin_addr to Network Byte Order, digi-dot 
//      is already NBO
uint32_t DTB::SockaddrIn::setSinNboAddr(std::string 
                                        a_nboDigiDotHostnameStr)
{
   //       hbo     = convert (nbo)
   uint32_t retVal = ntohl(sin_addr.s_addr);
   //
   int status = inet_aton(a_nboDigiDotHostnameStr.c_str(), &sin_addr);

   if(0 == status) // NOTE: 0 when failure! unusual
      throw(a_nboDigiDotHostnameStr);

   return (retVal);
}
2785528
  • 5,438
  • 2
  • 18
  • 20