c - Linux 原始套接字 - ip header 中的字节顺序

标签 c linux sockets endianness

我想确认 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 标准中,每个字段都是按网络顺序排列的。您应该使用 ntohsntohl 函数将网络顺序转换为主机顺序,并使用 htonshtonl 函数将网络顺序转换为主机顺序将主机转换为网络顺序。这样,您的代码也可以在大端机器上正确编译。

IP 地址通常按网络顺序存储在内部,在这种情况下,可以使用 inet_ptoninet_ntop 将其转换为/自表示格式。因此,您通常不需要考虑这些地址的存储格式,除非您手动应用网络掩码等。如果您这样做,八位字节(字节到你和我)将按自然顺序存储,即 111.222。 33.44按照111、222、33、44的顺序存储。仔细想想,这是一个大端顺序。

关于c - Linux 原始套接字 - ip header 中的字节顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28104827/

相关文章:

android - 如何通过Android应用程序进行USB网络共享?

c - C 中的 Char 矩阵 - 使用 Scanf 或 getchar

c - 需要从删除空格和字母的字符串中获取多个数字输入

C++ recvfrom 超时

当我尝试查找版本时,java安装错误

linux - 为什么不使用 EXIM 和 OpenDKIM 服务?

c++ - 服务器使用accept()接受连接后出现的问题

c - 有没有办法告诉C永远不要动态分配内存?

c - 为什么原始套接字改变了我的 TCP 校验和

html - sed 从 html 文件中删除标签