14

此代码在最后一行引发 ArgumentOutOfRangeException

var initAddress = IPAddress.Parse("1.65.128.190");
var ipv6Address = initAddress.MapToIPv6();
Assert.IsTrue(ipv6Address.IsIPv4MappedToIPv6);
var ipv4Address = ipv6Address.MapToIPv4();

谁能解释为什么 MapToIPv6() 和 MapToIPv4() 不兼容往返?

编辑:异常源自 IPAddress 构造函数,由 MapToIPv4() 调用。

此外,当第一行是

var initAddress = IPAddress.Parse("1.65.128.90");

不再抛出异常

编辑2:@Luaan 复制了这个,我添加了标签 [bug-reporting]。还添加了 [bcl]。让我们看看是否有任何 MS 人员跟踪这些标签 :)

edit3:在 Connect https://connect.microsoft.com/VisualStudio/feedback/details/871964报告

4

1 回答 1

18

好的,我实际上已经验证了这一点,所以让我将其发布为答案。

IPAddress地址映射回 IPv4 时,该类出现错误。

根据 .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 中进行按位运算的任何人来说,这个问题应该是非常明显的——数字都是ints。所以移动第二个ushort( m_Numbers[7]) 将给出一个负值,因为最高有效位是1。这意味着所有以高于 的字节结尾的 IPv4 地址127在从 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
 );

只需在进行位移之前将其转换int为 a就可以了。uint

当您考虑有符号类型时,按位运算可能会非常棘手。我猜代码是从 C++ 库或其他东西中复制的,这个问题不会出现。

于 2014-05-12T12:42:57.370 回答