[返回]
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