3

当我发现一些奇怪的东西时,我正在修补 IP 数据包“解析器”。

在解析 IP 地址时,在 C# 中

private uint srcAddress; 
// stuff
srcAddress = (uint)(binaryReader.ReadInt32());

成功了,所以你会认为这个 VB.Net 等价的

Private srcAddress As UInteger
'' stuff
srcAddress = CUInt(binaryReader.ReadInt32())

也会成功的。它没有。这 :

srcAddress = reader.ReadUInt32()

不过会。

花了一些时间去发现,但我发现了什么——如果有的话?为什么是这样 ?

4

1 回答 1

5

默认情况下,VB.NET 执行 C# 默认不执行的操作。它总是检查数字溢出。这在您的代码中触发,最后一位为 1 而不是 0 的 IP 地址将产生一个负数,并且无法转换为 UInteger。一种只能存储 32 位正数的数据类型。

C# 也有这个选项,你必须在代码中显式地使用checked关键字。或者使用 VB.NET 项目默认打开的相同选项:项目 + 属性,构建选项卡,高级,勾选“检查算术上溢/下溢”复选框。VB.NET 项目中的相同选项名为“删除整数溢出检查”,默认为关闭。

请注意这些默认值如何影响语言的语法。在 C# 中,您必须编写强制转换以将值转换为不兼容的值类型。在 VB.NET 中不是必需的,运行时检查使您免于麻烦。这是一种非常糟糕的麻烦,溢出会产生非常糟糕的结果。在您的情况下,这种情况不会发生,IP 地址实际上是一个无符号数字。

请记住关于 IP 地址的另一个怪癖,套接字最初是在由 LSD 和大端处理器驱动的 Unix 机器上发明的。您通常必须使用 IPAddress.NetworkToHostOrder() 以正确顺序获取地址。仅具有以有符号整数类型作为参数的重载。所以使用 ReadInt32() 实际上是正确的,假设它是一个 IPv4 地址,你直接将它传递给 NetworkToHostOrder()。不怕溢出。

于 2014-06-07T16:04:01.427 回答