阅读关于如何以最佳方式表示 IPv6 地址的 RFC 建议 ( RFC 5952 ),我尝试在 C++ 中实现一个函数,该函数将字节数组转换为适当的文本表示,即std::string
.
为了检查我的代码是否正确,我将我的结果与inet_ntop
( #include <arpa/inet.h>
) 返回的结果进行比较。请注意,我实际上使用的是 Windows 等效的#include <ws2tcpip.h>
.
在大多数情况下,我的函数具有相同的行为,并且我完全理解基本规则(省略前导零,通过用“::”替换它来压缩最长的零块,等等)。
但有趣的部分如下:据我了解,对于一些特殊地址(IPv4 映射、IPv4 兼容和 IPv4 转换的 IPv6 地址,请参阅RFC 2765),建议以其他十六进制表示法表示IPv4 地址常用的点分十进制表示法的最后 4 个字节。
例如::ffff:0:168.0.0.1
,::ffff:168.0.0.1
和::168.0.0.1
在其推荐的文本表示中都是有效的 IPv6 地址,并且inet_ntop
也得出了该结论。
现在我的问题0:0:0:0:0:ffff:0.0.1.1
是:根据 ,IPv6 地址inet_ntop
缩短为::ffff:0:101
,再次选择十六进制表示。这种行为的原因是什么?我认为因为我们在这里有一个特殊的地址前缀,所以无论最后 4 字节块的前两个字节是否为零,都将使用点分十进制表示法,因此将其写为::ffff:0.0.1.1
. 我是误解了 RFC 建议还是inet_ntop
在这方面不一致?我观察到这inet_ntop
在我的所有其他测试用例中都非常符合 RFC。
我希望你能帮助我。
编辑:经过更多测试后,似乎inet_ntop
确实总是选择十六进制表示法而不是点分十进制表示法,即使 IPv6 地址实际上只是那些特殊的嵌入式 IPv4 地址中的一些,如果最后 4 的前两个字节字节块为零。