C-inet_pton()不产生网络字节顺序

时间:2018-12-06 07:09:57

标签: c sockets networking network-programming endianness

我对inet_pton()函数感到困惑。根据{{​​3}}

  

此功能将字符串 src 转换为af地址族中的网络地址结构,然后将网络地址结构复制到 dst 。 af参数必须是AF_INET或AF_INET6。 dst 以网络字节顺序编写。

因此该函数产生网络字节顺序值。但是我得到了这段代码:

 struct sockaddr_in a;
 char sip[20];
 inet_pton(AF_INET, "192.168.0.182", (void *)&a.sin_addr);
 inet_ntop(AF_INET, (void *)&a.sin_addr, sip, 20);

 printf("htonl:%08x\n", htonl(a.sin_addr.s_addr));
 printf("inet_pton:%08x\n", a.sin_addr.s_addr);
 printf("inet_ntop:%s\n", sip);

输出:

htonl:c0a800b6
inet_pton:b600a8c0
inet_ntop:192.168.0.182

inet_pton的输出为b6.00.a8.c0,它转换为182.0.168.192,它也与htonl的输出不同。

由于htonl将主机字节顺序转换为网络字节顺序,所以如果inet_pton产生网络字节顺序,我想它们的输出应该相同吗?这是否意味着inet_pton实际上产生了主机字节顺序?

如果inet_pton已经产生了network byte order,为什么我需要htonl才能获得正确的值?

1 个答案:

答案 0 :(得分:3)

是的,inet_pton按照网络顺序将地址字节放入目标缓冲区。让我们来看一个例子,看看会发生什么。使用您的地址“ 192.168.0.182”,inet_pton会产生以下四个字节:

c0   a8  00  b6    (hex)
192  168 0   182   (dec)

网络字节顺序。然后,您致电htonl(实际上并不正确-您应该致电ntohl网络订单转换为主机订单,但正如@ZanLynx指出的那样,两者x86上的功能相同),您可以将字节重新排序为:

b6 00 a8 c0

但是随后您将表单以printf的格式传递给%x。这告诉printf将四个字节解释为单个32位整数,但是x86是一点字节顺序的机器,因此当将四个字节作为整数加载时,b6是最低顺序的字节而c0是最高的,它会产生您所看到的:

htonl:c0a800b6

因此,通常,如果您具有网络形式的IPv4地址,并且想要按对您(作为程序员)“有意义”的顺序快速显示(用于调试或其他方式),则可以使用:

printf("%x\n", ntohl(a.sin_addr.s_addr));

您还可以按网络顺序显示单个字节(这是完全相同的东西,但可能更容易缠住您的头),只需使用unsigned char *(或等效的{{1} } uint8_t *中的}来打印各个字节:

<stdint.h>

(您需要在此处使用无符号类型,以避免符号扩展。在上面的语句中,每个字符将在对uint8_t *ipp = (void *)&a.sin_addr.s_addr; printf("%02x %02x %02x %02x\n", ipp[0], ipp[1], ipp[2], ipp[3]); 的调用中提升为int。如果您已签名{ {1}}包含0xc0,通常会将其符号扩展到32位printf中:0xffffffc0。或者,您可以使用格式规范{{1 }}明确告诉char,您实际上是在将它传递给int;然后,它只会查看每个提升的"%02hhx"的最低顺序字节。)