65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 VBScript 计算子网范围

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (3投票s)

2010年4月14日

CPOL

4分钟阅读

viewsIcon

58050

downloadIcon

813

这是我的一次探索之旅——我开始编写一个脚本,并学到了更多。

引言

这可能是你能找到的最简单的 VBScript 子网计算器。直到今天,我只找到了另一个。“什么?”你可能会说,“网上有很多子网计算器!” 是的,但是它们不是用 VBScript 编写的,而 VBScript 仍然是许多系统管理员的选择语言。

背景

我一直在使用 okstorms 的这段代码片段 来为多个脚本解析 IP 和子网掩码中的子网,说实话,它一直工作得很完美,我甚至都没有仔细研究它到底是如何实现其神奇功能的。

最近,我编写了一个脚本,用于列出给定 IP 所在同一子网中的所有主机,并且再次使用了 okstorms 的可靠代码,同时还使用了 Phil Calderone 的子网表 来查找主机数量。

经过一些测试,我并不满意;

  1. 我不知道 okstorms 的子网代码究竟是如何工作的,而且
  2. 新脚本奏效了,但我对其结果的 100% 可靠性没有信心。

随后我发现Phil Calderone 的子网表已过时,这让我震惊,因为我曾用它来通过 2001 年的 MCSC TCP/IP 考试。

Using the Code

在这些发现之前,我决定从头开始编写自己的子网计算器,并基于 Phil 的子网表。我创建的脚本相当冗长,因为它执行的是“手工”计算,类似于人类使用表格的逻辑。

VBScriptSubnetCalc.gif

脚本似乎工作得很好,它返回了目标子网范围的第一个和最后一个 IP,甚至迭代了该范围内的所有地址。我对其工作感到自信,因为结果与我的子网表相符,但我的世界却开始崩塌。当我用它测试一些 在线子网计算器 时,有时会得到不同的结果?

VBScriptSubnetCalc.jpg

进一步调查发现,问题出在我的子网表上,我曾认为它坚如磐石,由微软发布和推广,但现在却已过时。谁会想到像子网范围定义这样的东西会改变。 此页面 指向了 RFC 1878,其中解释了排除包含全零或全一的子网的做法现在已过时。啊,谜题解开了。

好吧,回到原点。我需要的是一个不依赖于表格或其他复杂的八位组计算的子网计算器,而是基于简单的二进制级别工作。我仔细研究了 okstorms 的子网计算器,并惊讶于它将 IP 转换为二进制、计算子网位数,然后根据该长度截断 IP 返回 SubnetID 的简洁方式。

Function Subnet(strAddress, strMask)
   'condensed version of okstorms’ subnet function
   lenSN = Len(Left(str2bin(strMask), InStr(str2bin(strMask), "0") - 1))
   Subnet = bin2str(Left(str2bin(strAddress), lenSN) & String(32 - lenSN, "0")) 
End Function 

不幸的是,我需要的不仅仅是这些,但在稍作实验后,我发现我也可以通过在二进制中计算 (IP AND Subnet Mask) 来获得目标范围的第一个地址 (subnetID)。更重要的是,范围的最后一个地址(广播地址)可以通过在二进制中计算 (IP OR Subnet Mask) 来获得。

   'IP and SN to find Network addresses
   for c=32 to 1 step -1
      temp=(cint(mid(binIP,c, 1)) and cint(mid(binSNM,c, 1))) & temp
   next
   netwAdd=temp : temp=""

然后,要找到主机数量,我只需要从最后一个主机中减去第一个主机,但 VBScript 并不原生支持二进制计算。所以我编写了两个函数 binAdd() binSub() 来执行 32 位二进制加法和减法。我相信这两个函数可以通过更多的数学技巧来编写,但它们相当有效。

在这里的代码片段中,我将两个二进制数相加。我首先尝试使用复杂的逻辑来创建一个精巧的数学函数,但决定必须使用循环,并决定采用与用纸笔计算相同的逻辑。(快速编码,而且不算太糟糕。)

function binAdd(binA,binB)
'add two 32bit binary numbers together

   c=0
   for i=32 to 1 step-1
      a=cint(mid(binA,i,1))
      b=cint(mid(binB,i,1))
      if a=0 and b=0 and c=0 then 
         add=0  : c=0 
      elseif a=1 and b=0 and c=0 then 
         add=1  : c=0 
      elseif a=0 and b=1 and c=0 then 
         add=1  : c=0 
      elseif a=1 and b=1 and c=0 then 
         add=0  : c=1 
      elseif a=1 and b=1 and c=1 then 
        add=1  : c=1
      elseif a=1 and b=0 and c=1 then 
         add=0  : c=1
      elseif a=0 and b=1 and c=1 then 
         add=0  : c=1 
      elseif a=0 and b=0 and c=1 then 
         add=1  : c=0
      else
         msgbox "Error this function is only for adding 2 32bit binary numbers together"
         binAdd=0 : exit function
      end if
      total=add&total
   next
   binAdd=total

end function

工作完成了,我现在有一个基于二进制级别的子网计算器,我完全理解它的工作原理,并且对其结果充满信心。

VBScriptSubnetCalc.PNG

此版本的脚本还输出二进制等价物,如果您想了解其二进制级别的工作原理,这将非常有用。在我看来,这对于理解 IP 子网至关重要。

关注点

这次脚本编写之旅让我更深入地了解了子网世界的复杂性。我有点觉得那些曾经无效的子网范围是对 IP 地址空间的浪费,显然有人也这么认为并对此采取了行动。

文章开头附有我基于 Phil Calderone 子网表的第一版子网计算器尝试,顺便说一句,谢谢 Phil,我通过了 TCP/IP 考试。

此外,您还会找到我的最终代码。感谢 okstorms 的子网计算器,它被用于我们 IT 分支机构每天使用的桌面管理工具以及我多年来编写的许多其他脚本中。现在,它激发了这段代码,它实现了与您的代码相同的功能,并计算子网中的主机数量。

祝好!

历史

  • 2010 年 4 月 14 日:初始帖子
© . All rights reserved.