[返回]
计算机世界2001年第2期

IP地址的动态分配

华中理工大学汉口分校计算机中心 李 轶

  在局域网络的 IP地址分配中,我们通常采用 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议 )服务器自动分配 IP地址。这可以避免 IP地址冲突,同时还能定制所分配的 IP环境,如指定网关、 DNS( Domain Name System)服务器等。

提出问题

由于 DHCP的高度灵活性,所以不能保证对同一台机器每次都能分配相同的 IP地址。这一点在校园实验网络环境下最为明显,由于机器 IP地址的不确定性,无法通过 IP地址来判断这台机器属于哪个实验室,因而也不能确定能否对其开放某些网络服务。特别是在上实验课的时候, IP地址的混乱严重地影响了对实验网络的管理。

虽然 DHCP具有为特定机器保留 IP地址的功能,但若要求对局域网中的某一部分机器分配具有某一特征的 IP地址时,比如要求某个实验室的所有机器的 IP地址为 128.168.15.XXX,子网掩码为 255.255.0.0,此时设置将会非常烦琐。而且对每台机器手动设置固定 IP地址也非常费时、费力。因此,自己编写程序实现 IP地址的动态分配就显得尤为必要。

分析问题

IP地址是由网络地址和主机地址所组成。在程序中可根据每个实验室来直接给机器指定网络地址,为避免主机地址的冲突,根据网卡的 MAC地址的唯一性,由 MAC地址来确定主机地址(更简单的方法是直接使用随机数来产生主机地址)。 MAC地址是一个 48位的二进制数,每块网卡各不相同,每个网卡生产商都有一段或几段 MAC地址。笔者的方法是取出 MAC地址的高 8位( 2位 16进制数)和低 24位( 6位 16进制数),一起拼成一个无符号 32位二进制数,将其转换为 10进制后,用 254来取模产生一个主机地址(每个实验室的机器一般不会超过 254台)。

我们可以通过 winipcfg.exe获得 MAC地址。至于 IP地址的设定只需在 Windows注册表中写入相应的键值即可。

在机器上运行程序时,还需要禁止他人修改网络配置及运行注册表编辑器。同时,为防止有人编写恶意的 Windows脚本程序,还要将 Windows脚本的运行程序 WScript.exe和 CScript.exe删除。

解决问题

本文中的程序是用 VB Script写成,在 Windows 9x的 Windows Script Host环境支持下执行。当然,也可以由其他语言来实现。但采用 Windows脚本可以省去编译等过程,同时调试和修改也非常方便(只需要文本编辑即可)。 Windows脚本非常适合用于网络管理和系统维护等场合,而且在同 Norton Ghost配合使用后可大大提高 Windows系统的恢复效率。

程序部分代码如下:

ChangeIP.vbs

'根据机器的网卡号,设定该机器的 IP地址

'使用格式为: ChangeIP.vbs IP地址格式子网掩码

'例如: ChangeIP.vbs 128.168.15 255.255.0.0

'会将机器 IP地址设定为: 128.168.15.XXX

'主程序开始

Dim strNode

'获得网卡号

strNode = strGetNodeID()

'将 48位网卡地址拼接为 32位地址 (8位 16进制数 )

strNode = strLongIDToShortID(strNode)

Dim intIP

'将 8位 16进制数转换为 10进制数

intIP = intHexStrToInt(strNode)

'对其取模

intIP = intIP Mod 254

'将 IP地址写入注册表

call voidWriteIPToReg(intIP)

'关闭计算机

call voidShutDown()

'主程序结束

'获得网卡号

Function strGetNodeID()

Set WshShell=WScript.CreateObject(" WScript.Shell")

WshShell.Run" winipcfg.exe /all /batch c:\

NodeID.txt", 0, TRUE

Set Wshell=Nothing

Dim fso, theFile, ln

Set fso = CreateObject(" Scripting.FileSystemObject")

Set theFile = fso.OpenTextFile(" c:\NodeID.txt")

Do While theFile.AtEndOfStream < > True

ln = theFile.ReadLine

If InStr(ln," Adapter.")< >0 Then

ln = theFile.ReadLine

Exit Do

End If

Loop

Thefile.Close

fso.DeleteFile(" c:\NodeID.txt")

Set fso=Nothing

ln = Right(ln,17)

Dim I,strLast

For I=1 To 17 Step 1

If Mid(ln,i,1)< >"- " Then

strLast = strLast& Mid(ln,i,1)

End If

Next

strGetNodeID = strLast

End Function

'将 48位网卡地址拼接为 32位地址

Function strLongIDToShortID(LongID)

dim tmpStr

tmpStr = Left(LongID,2)& Right(LongID,6)

strLongIDToShortID = tmpStr

End Function

'将一个 16进制数转换为一个 10进制数

Function intHexStrToInt(strHex)

Dim i,Length,total

Length=len(strHex)

strHex=UCase(strHex)

For i=Length To 1 Step- 1

Dim intv

intv = Asc(Mid(strHex, Length- i+ 1,1))- 65

If intv >= 0 Then

total=total+ 16^(i- 1)* (10+ intv)

Else

total=total+ 16^(i- 1)* (intv+ 17)

End If

Next

intHexStrToInt =total

End Function

'将 IP地址写入注册表

Function voidWriteIPToReg(strIP)

Dim Wshell,objArgs,strIPStyle

Set objArgs = WScript.Arguments

strIPStyle = objArgs(0)

strIPMask = objArgs(1)

set objArgs=Nothing

Set WshShell=WScript.CreateObject(" WScript.Shell")

WshShell.RegWrite" HKLM\System\CurrentControlSet\"&"
Services\Class\NetTrans\0000\IPAddress", strIPStyle&" ."& strIP," REG_SZ"

WshShell.RegWrite" HKLM\System\CurrentControlSet\"&"
Services\Class\NetTrans\0000\IPMask", strIPMask," REG_SZ"

Set Wshell=Nothing

End Function

'关闭计算机

Function voidShutDown()

Set WshShell=WScript.CreateObject(" WScript.Shell")

WshShell.Run" rundll32.exe user.exe,ExitWindows", 0, False

Set Wshell=Nothing

End Function


作者邮箱:leey22@netease.com