我想确认 ip header 中大于一个字节的任何值(short、int.. 或他们的替代 int16_t..)都应该使用 ntohs/ntohl 等转换为 big endian 以通过网络发送。
当使用普通套接字或使用其他技术时,内核是否在幕后管理了这一点?
这是一团糟,因为一些函数,比如使用 ioctl 获取接口(interface)的 ip 地址,似乎在转换为 sockaddr_in* 时已经以大端方式放置数据。它输出我的地址,如 36.2.168.192(带有 printf 的 %d),但 ifreq 输出它,如 192.168.2.36
代码
int addr = ((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr.s_addr;
printf("%d %d %d %d ", (addr >> 24) & 255 , (addr >> 16) & 255,(addr >> 8) & 255, (addr) & 255);
以相反的顺序给我我的IP地址
而使用
for (int _x = 0; x < 14; ++_x) {
printf("%d ", ifr.ifr_ifru.ifru_addr.sa_data[_x] );
}
会以正确的顺序 (192.168.2.36) 向我提供一些零,然后是零。 哇..我迷路了。
如果你问我的话,那是一片丛林。
问题
什么要转换成大端,什么不转换?
最佳答案
最好不要将其视为大端或小端,而是主机顺序(可能是其中之一)和网络顺序(大端)。你是正确的,在 IP 标准中,每个字段都是按网络顺序排列的。您应该使用 ntohs
和 ntohl
函数将网络顺序转换为主机顺序,并使用 htons
和 htonl
函数将网络顺序转换为主机顺序将主机转换为网络顺序。这样,您的代码也可以在大端机器上正确编译。
IP 地址通常按网络顺序存储在内部,在这种情况下,可以使用 inet_pton
和 inet_ntop
将其转换为/自表示格式。因此,您通常不需要考虑这些地址的存储格式,除非您手动应用网络掩码等。如果您这样做,八位字节(字节到你和我)将按自然顺序存储,即 111.222。 33.44按照111、222、33、44的顺序存储。仔细想想,这是一个大端顺序。
关于c - Linux 原始套接字 - ip header 中的字节顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28104827/