此代码在最后一行抛出ArgumentOutOfRangeException
var initAddress = IPAddress.Parse("1.65.128.190");
var ipv6Address = initAddress.MapToIPv6();
Assert.IsTrue(ipv6Address.IsIPv4MappedToIPv6);
var ipv4Address = ipv6Address.MapToIPv4();
有谁可以解释为什么MapToIPv6()和MapToIPv4()不兼容往返?
编辑:异常来自IP地址构造函数,由MapToIPv4()调用。
此外,第一行是
var initAddress = IPAddress.Parse("1.65.128.90");
不再抛出异常
edit2:当@Luaan转载这个时,我添加了标签[bug-reporting]。还添加了[bcl]。让我们看看是否有MS人员跟踪这些标签:)
edit3:在Connect https://connect.microsoft.com/VisualStudio/feedback/details/871964
报告答案 0 :(得分:18)
好的,我实际上已经验证了这一点,所以让我发布这个作为答案。
将地址映射回IPv4时,IPAddress
类出错。
根据.NET参考代码,它执行此操作:
long address =
(((m_Numbers[6] & 0x0000FF00) >> 8) | ((m_Numbers[6] & 0x000000FF) << 8)) |
((((m_Numbers[7] & 0x0000FF00) >> 8) | ((m_Numbers[7] & 0x000000FF) << 8)) << 16);
任何在.NET中进行按位操作的人都应该明白这个问题 - 数字都是int
。因此,移动第二个ushort
(m_Numbers[7]
)会给出一个负值,因为最重要的位是1
。这意味着所有以高于127
的字节结尾的IPv4地址在从IPv6映射时都会导致错误。
简单的解决方法就是:
long address =
(((m_Numbers[6] & 0x0000FF00) >> 8) | ((m_Numbers[6] & 0x000000FF) << 8))
|
(
(uint)(((m_Numbers[7] & 0x0000FF00) >> 8) | ((m_Numbers[7] & 0x000000FF) << 8))
<< 16
);
只需在执行bitshift之前将int
强制转换为uint
即可。
当您考虑签名类型时,按位操作可能非常棘手。我想这些代码是从C ++库中复制而来的,这个问题不会出现。