在以下代码中,addr_min
和addr_max
是表示IPv4地址的32位无符号值,它们按网络字节顺序排列,即big-endian格式:
uint32_t addr;
for (addr = addr_min; addr <= addr_max; addr = addr + htonl(1)) {
...
}
因此,假设我想迭代地址1.2.0.0
,并逐渐增加第三个和第四个八位字节,从而总共产生65534个地址(打印时的addr_max
显示feff0201(。我原以为上面的代码会起作用,但它只将第四个八位字节更改为值0xfe,而从不触及第三个。
我可能做错了什么?
您不打算对已按网络字节顺序编码的值进行任何算术运算。在这种情况下,您可能只添加到最高阶字节。
快速的答案是:
uint32_t val_n = htonl(init_val);
val_n += htonl(1);
不等同于
uint32_t val = init_val;
val += 1;
uint32_t val_n = htonl(val);
其中,val
和init_val
是常规主机顺序值,val_n
是网络顺序编码。
网络阶数值对算术没有直接的用处。您不知道htonl(1)
会将什么值添加到您的值中,也不知道添加它会导致下一个字节在最低字节上达到255之后翻转。不要把网络顺序值看作是数字,把它们看作是有意义的不透明值。
将您使用的所有内容按主机顺序保存为实际数字:
uint32_t addr;
for (addr = addr_min; addr <= addr_max; addr += 1) {
uint32_t addr_net_order = htonl(addr);
...
}
其中addr
、addr_min
和addr_max
都是主机顺序,即如果addr_min
应该是1.2.0.0
、addr_min = 0x01020000
。