IP地址合法性判断及子网检测大学课程设计实验报告Word格式.docx
《IP地址合法性判断及子网检测大学课程设计实验报告Word格式.docx》由会员分享,可在线阅读,更多相关《IP地址合法性判断及子网检测大学课程设计实验报告Word格式.docx(28页珍藏版)》请在冰豆网上搜索。
Windowsxp(WindowsNT以上版本皆可)
编程环境:
MicrosoftVisualStudio2008(兼容MSVS2005,亦可使用VC6.0等)
编程语言:
C++
测试环境:
MS-DOS
2.硬件
现阶段常见PC
四.实验方法
Part1实验原理
我们说过因特网是把全世界的无数个网络连接起来的一个庞大的网间网,每个网络中的计算机通过其自身的IP地址而被唯一标识的,据此我们也可以设想,在Internet上这个庞大的网间网中,每个网络也有自己的标识符。
我们把计算机的IP地址也分成两部分,分别为网络标识和主机标识。
同一个物理网络上的所有主机都用同一个网络标识,网络上的一个主机(包括网络上工作站、服务器和路由器等)都有一个主机标识与其对应IP地址的4个字节划分为2个部分,一部分用以标明具体的网络段,即网络标识;
另一部分用以标明具体的节点,即主机标识,也就是说某个网络中的特定的计算机号码。
另一方面,只有在一个网络号下的计算机之间才能"
直接"
互通,不同网络号的计算机要通过网关(Gateway)才能互通。
但这样的划分在某些情况下显得并十分不灵活。
为此IP网络还允许划分成更小的网络,称为子网(Subnet),这样就产生了子网掩码
1.IP的寻址规则
(1).ip分类规则
a、网络地址必须唯一。
b、网络标识不能以数字127开头。
在A类地址的第一位为0,数字127保留给内部回送函数。
B类地址的前两位为10;
C类地址的前三位为110;
D类地址的前四位为1110;
E类地址的前五位为11110。
c、网络标识的第一个字节不能为255。
数字255作为广播地址。
d、网络标识的第一个字节不能为“0”,“0”表示该地址是本地主机,不能传送。
e、不合法的IP地址类型:
123..2.1
123.23$.2.1
123.2345.2.1
123.23.45.1
2.主机寻址规则
a、主机标识在同一网络内必须是唯一的。
b、主机标识的各个位不能都为“1”,如果所有位都为“1”,则该机地址是广播地址,而非主机的地址。
c、主机标识的各个位不能都为“0”,如果各个位都为“0”,则表示“只有这个网络”,而这个网络上没有任何主机。
3.确定子网掩码数
用于子网掩码的位数决定于可能的子网数目和每个子网的主机数目。
在定义子网掩码前,必须弄清楚本来使用的子网数和主机数目。
定义子网掩码的步骤为:
a、确定哪些组地址归我们使用。
比如我们申请到的网络号为“128.73.a.b”,该网络地址为B类IP地址,网络标识为“128.73”,主机标识为“a.b”。
b、根据我们现在所需的子网数以及将来可能扩充到的子网数,用宿主机的一些位来定义子网掩码。
比如我们现在需要12个子网,将来可能需要16个。
用第三个字节的前四位确定子网掩码。
前四位都置为“1”,即第三个字节为“11110000”,这个数我们暂且称作新的二进制子网掩码。
c、把对应初始网络的各个位都置为“1”,即前两个字节都置为“1”,第四个字节都置为“0”,则子网掩码的间断二进制形式为:
“11111111.11111111.11110000.00000000”
d、把这个数转化为间断十进制形式为:
“255.255.240.0”这个数为该网络的子网掩码。
4.IP掩码的标注
A、无子网的标注法
对无子网的IP地址,可写成主机号为0的掩码。
如IP地址210.73.140.5,掩码为255.255.255.0,也可以缺省掩码,只写IP地址。
B、有子网的标注法
有子网时,一定要二者配对出现。
以C类地址为例。
IP地址中的前3个字节表示网络号,后一个字节既表明子网号,又说明主机号,还说明两个IP地址是否属于一个网段。
如果属于同一网络区间,这两个地址间的信息交换就不通过路由器。
如果不属同一网络区间,也就是子网号不同,两个地址的信息交换就要通过路由器进行。
例如:
假设maskwe为27,对于IP地址为210.73.140.5的主机来说,其主机标识为00000101,对于IP地址为210.73.140.16的主机来说它的主机标识为00010000,以上两个主机标识的前面三位全是000,说明这两个IP地址在同一个网络区域中,这两台主机在交换信息时不需要通过路由器进行;
210.73.60.1的主机标识为00000001,210.73.60.252的主机标识为11111100,这两个主机标识的前面三位000与011不同,说明二者在不同的网络区域,要交换信息需要通过路由器。
其子网上主机号各为1和252。
Part2具体实现
通过以上的原理,我们就知道了在检验IP地址和子网检验时应该明确的问题,关键的两点就是把输入的IP分解成各段,然后判断子网号,掩码和ip地址的基本格式是否合法,
其次:
如果三者的基本格式都合法,才调用断定,ip地址是否为子网成员,的函数。
该函数同时判别子网号与掩码是否匹配,子网号为全0或全1,主机号为全0、全1。
1.实现流程
2.编程
本部分的编程的主要目的是算法的实现,主要的方法是C++中字符串处理。
(1)类设计
a.属性
charip[15];
//用于存放ip地址
charip_Temp[15];
//用于存放ip地址
charsubnet_mask[18];
//用于存放subnet_mask地址
charsubnet[18];
//用于存放subnet地址
charsubnet_Temp[18];
intmask;
//用于存放mask(1的个数)
boolmaskIsValid;
//用于判断的个数是否合适,或是否与subnet匹配
b.方法
构造函数,析构函数:
ipTest(char*,char*);
//自定义初始化类函数
~ipTest();
//析构函数
主判断函数(即主要的方法):
voidAllJudgment();
//判断mask,subnet,ip的合法性问题
boolipIsValid(char*);
//判断ip是否合法
BoolsubnetIsValid(char*);
//判断子网号subnet是否合法
boolNoIllegalChar(char*);
//ip,subnet地址中非法字符的判断
boolmaskIsMatSubnet(int,char*);
//判断mask与subnet是否匹配
工具函数:
voidprint();
//判断ip是否为子网成员,并输出判断结果
voidsplit(char*,int*);
//把单个字符地址转换为十进制数值型地址(含四段)
InttoBinary(inta);
//十进制int型数据转换为二进制int型数据
char*toString(int*a);
//把二进制int型数据转换为一个整体的二进制字符型数据
(2)主函数
intmain(intargc,char*argv[])函数
•1.获取参数
•2.简单判断参数格式(长度)
•3.若是正常参数,实例化ipTest类
•4.调用主判断函数voidAllJudgment()判断
•5.输出结果
(3)程序流程
(4)头文件
#include<
iostream>
stdlib.h>
stdio.h>
string.h>
math.h>
ctype.h>
usingnamespacestd;
五.实验分析及测试
本部分测试了正常输入和非法输入时,程序对输入的判断,编程的环境为VS2008,在解决方案文件夹下面的Debug文件夹里面生成可执行文件;
运行MS-DOS,进入Debug文件夹进行测试。
1.算法正确性检测
(1)用正确格式和合法的数据的输入,测试Mask和IP的匹配
测试数据:
IP:
128.196.33.12
Mask:
15和16
分析:
IP:
128.196.33.12属于B类IP地址,前16位位网络段,后16位为主机段,所以Mask至少为16
结果截图:
(2)用正确格式和合法的数据的输入,测试主网和子网的匹配
主网IP:
子网IP:
128.196.127.17和128.196.63.17
Mask:
18
分析:
主网IP和子网IP都是属于B类IP地址,前8位为网络段,后8位为主机段,Mask至少为16由于Mask为18,可知道在主机段中前两位,也就是IP地址的第9,10位为子网号(18-16=2);
而B类IP地址的子网掩码为255.255.0.0
所以可知:
128.196.33.1210000000.11000100.00100001.00001100
2位相于,得:
00
Mask:
255.255.0.011111111.11111111.00000000.00000000
2位相于,得:
01
128.196.127.1710000000.10000100.01111111.00010001
结果为不匹配。
截图:
128.196.63.1710000000.10000100.00111111.00010001
结果为匹配。
(3)补充说明:
i)主网和子网匹配的时候,实际上的与运算的位数是Mask个数,即Mask有多少,就相与前多少个位。
而以上例子中可知,B类IP地址的子网掩码为255.255.0.0,所以前8位全是1,所以无论IP是多少,相与结果都是1,即不用考虑网络段,直接相与主机段的前n段即可,n=(mask-所属网络分类的主机段位数)。
本测试例子中位2。
ii)考虑
(2)中的两个3个IP地址可以发现当主网IP为128.196.33.12,mask为18时,IP和子网掩码相与,主机号前两位为00,所以可推出,子网IP的只需要主机段的前两位为00,则都可以匹配,即子网IP的第3节(第17位到第24位)为00XXXXXX,转化为十进制就是小于63的整数就可以匹配。
2.输入合法性测试
本实验程序规定输入的标准参数输入格式为:
X.X.X.X/MASKX.X.X.X,其中:
X为0-255的十进制整数,mask为0-32的十进制整数,两个IP地址中间用空格分开,IP地址的为4段,每一段都用“.”分开,IP地址中允许出现空格或其他字符
(1)输入的IP地址中含有非法字符
128.196.33.a2
子网IP:
12e.196.127.17
Mask:
1h
结果截图:
(2)输入的IP地址段数不正确
128..33.12
126.196.
(3)没有输入mask
128.196.33.11
结果截图:
(4)输入mask超出合法范围
测试数据:
子网IP:
128.196.33.11
Mask:
35
(5)输入IP超出合法范围
555.196.33.12
128.999.33.11
25
结果截图:
(6)特殊的IP地址
0.0.0.0
127.1.1.1
255.255.255.255
六.实验结论
本实验根据现在通用的IP地址分配使用规则,设计实验算法,运用C++字符转函数处理,程序实现了基本要求的功能,考虑到了多方面的因素;
另一方面,设计之初的思路把此程序定位在接口工具程序,所以省略掉UI的设计,考虑到了扩展性的方面需要,程序提供简单、方便的接口和较为简单参数,方便扩展使用。
仍存在的问题:
数据结构的设计不够清晰简练和方便使用,可读性不太好;
主函数流程存在一定的问题,理路不是很清晰,主要是类的各个方法的设计没有总体考虑,设计之初没有考虑,在需要时才加,导致程序结构有点乱,不易阅读和检查。
七.附录源代码
说明:
源文件语言:
文件数:
1
源文件名:
ipTest.cpp
//ipTest类定义
classipTest{
charip[15];
charip_Temp[15];
charsubnet_mask[18];
charsubnet[18];
charsubnet_Temp[18];
intmask;
boolmaskIsValid;
public:
ipTest(char*,char*);
~ipTest(){};
//析构函数
boolipIsValid(char*);
boolsubnetIsValid(char*);
//判断子网号subnet是否合法
boolNoIllegalChar(char*);
//ip,subnet地址中非法字符的判断
boolmaskIsMatSubnet(int,char*);
voidAllJudgment();
voidprint();
voidsplit(char*,int*);
//把单个字符地址转换为十进制数值型地址(含四段)
inttoBinary(inta);
//十进制int型数据转换为二进制int型数据
char*toString(int*a);
//把二进制int型数据转换为一个整体的二进制字符型数据
};
//main主函数
intmain(intargc,char*argv[])//自动读取数据
{
//cout<
<
"
目录地址:
argv[0]<
endl;
//argv[0]表示ipTest.exe的保存目录地址
cout<
subnet_mask:
"
argv[1]<
//argv[1]表示第二个参数,即subnet/mask
ip地址:
argv[2]<
endl<
//argv[2]表示第三个参数,即ip
//判断段数是否输入合法
if(argc!
=3)//argc表示输入的参数个数,无参数输入时,其值为,因为默认argv[0]总是有的
{
cout<
输入非法!
;
return0;
}
else
//先简单判断subnet/mask的长度
if(strlen(argv[1])>
18)
{
cout<
subnet/mask输入非法!
system("
pause"
);
return0;
}
//先简单判断ip的长度
if(strlen(argv[2])>
15)
ip输入非法!
ipTesttest(argv[1],argv[2]);
//实例化类,传入两个参数
test.AllJudgment();
//调用函数,判断mask,subnet,ip的合法性问题
system("
//系统暂停
return0;
}
//构造函数
ipTest:
:
ipTest(char*subnet_mask,char*ip)
maskIsValid=true;
//设置maskIsValid默认为合法
chartemp[2];
//定义变量
inti,len;
len=strlen(subnet_mask);
/*******************从subnet/mask中分离出subnet地址***************/
for(i=0;
i<
len&
&
subnet_mask[i]!
='
/'
i++)
this->
subnet[i]=subnet_mask[i];
subnet_Temp[i]=subnet_mask[i];
subnet_Temp[i]='
\0'
subnet[i]='
/**************************判断mask是否为数值************************/
if((len-(i+1)<
3&
len-(i+1)>
0))//判断mask是否为一/二位字节
if(len-(i+1)==1)//表明mask是一位
temp[0]=subnet_mask[i+1];
//判断字符是否为数值型字符
if(!
isdigit(temp[0]))//isdigit()为库函数,可以调用
{
cout<
mask中含有非数字的非法字符,error!
maskIsValid=false;
//mask不是数值,则设置为false
}
elseif((len-3)==i)//表明mask是二位
temp[1]=subnet_mask[i+2];
(isdigit(temp[0])&
isdigit(temp[1])))
mask=atoi(temp);
//自动把数字字符转换为对应的十进制数值的函数
if(mask<
0||mask>
32)
maskIsValid=false;
else//表明mask为空或字节超出范围
mask为空或超出范围,error!
maskIsValid=false;
//若mask是三位数,则表明mask输入非法(其实为~32)
/********************************************************************/
strcpy(this->
subnet_mask,subnet_mask);
//给subnet_mask赋值
ip,ip);
//给ip赋值
ip_Temp,ip);
//给ip_temp赋值
//判断mask,subnet,ip的合法性问题
voidipTest:
AllJudgment()
//设置标志subnet地址是否合法的bool型变量,并调用subnetIsValid函数判断
boolsubnetIsV=subnetIsValid(subnet_Temp);
//设置标记ip地址是否合法的bool型变量,并调用ipIsValid函数判断
boolipIsV=ipIsValid(ip_Temp);
//设置标记mask与subnet地址是否匹配的bool型变量,并调用maskIsMatSubnet函数判断
boolmaskIsMatSub=maskIsMatSubnet(mask,subnet_Temp);
/************************判断返回的值是否为真******************/
if(!
maskIsValid)//表示返回的maskIsValid是false
mask输入非法!
(mask为整数并在-32范围内)"
cou