树莓派上的字节序问题

6

我刚开始在C ++中进行一些原始网络编程,并且一直在树莓派上编译(没有交叉编译)。这使得一切都是小端。

在构建IP头之后,我计算了IP校验和,但结果总是不正确(基于此处的示例 http://www.thegeekstuff.com/2012/05/ip-header-checksum/)。

通过使用gdb,我将我的问题定位到了IP头中前32位的顺序。该示例使用0x4500003C,这意味着版本为4(0x4),IHL为5(0x5),TOS为0(0x00),tot_length为60(0x003C)。所以我设置了相同的数据包。

struct iphdr* ip; // Also some mallocing
ip->version = 4;
ip->ihl = 5;
ip->tos = 0;
ip->tot_len = 60;

现在在gdb中,我检查了前32位,期望得到0x3C000045因为字节序,但实际上我得到了这个:

(gdb) print ip
$1 = (iphdr *) 0x11018
(gdb) x/1xw 0x11018
0x11018:        0x003c0045

前16位是小端序(0x0045),但第二个包含十进制60的部分似乎是大端序(0x003C)!

这是怎么回事?是我疯了吗?我对结构体内部的字节顺序完全错了吗?(这是一种明确的可能性)


完全与您的问题无关 - 这个怎么样 - 想要一个吗 ;-) - Adrian Cornish
1
做吧!这值得每一分的3000个便士。 - John Sandbrook
2个回答

7

结构体内部的字段顺序和多字节字段内部字节的顺序是不同的。

0x003C 根本就没有字节序,它只是十六进制数值 60 的表示。当然,它会以某种字节序存储在内存中,但你用于写入字段的顺序和用于读取时使用的顺序是相同的 -- 它们都是树莓派本机的字节序,它们抵消了。

通常你会这样写:

ip->tot_len = htons(60);

在将一个16位字段存储到数据包中时,可以使用htons函数。对于32位字段,可以使用htonl函数,而对于从网络数据包中读取字段,则可以使用ntohsntohl函数。


啊,我在排除故障时深入了太多,错过了显而易见的答案。我曾尝试在读取我的头文件时使用htons,但它们仍然是无序的16位片段。在存储时使用它会对单个字段进行操作,而不是16位段,从而正确地存储东西。 - John Sandbrook

1

ARM架构可以运行小端和大端,但Android平台运行小端。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接