IP地址合法性判断及子网检测大学课程设计实验报告.docx
《IP地址合法性判断及子网检测大学课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《IP地址合法性判断及子网检测大学课程设计实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
IP地址合法性判断及子网检测大学课程设计实验报告
文档编制序号:
[KKIDT-LLE0828-LLETD298-POI08]
IP地址合法性判断及子网检测大学课程设计实验报告
四川理工学院
实验报告
实验名称
IP地址合法性判断及子网检验
课程名称
计算机科学与技术
姓名
成绩
班级
学号
日期
2013年1月
地点
计算机学院
一.实验目的
本设计要求编辑写程序,判断一个ip地址是否合法,并判断该地址是否属于一个给定子网,从而考察读者是否对ip地址概念及其子网划分有非常清楚的认识。
1加深对IP地址及subnet的认识;
2.了解IP地址的划分;
3.了解subnet的作用和产生因素,subnet的划分;
4.实际操作编写规则,匹配IP和subnet,加深理解
二.设计要求
在掌握ip地址表示方法及子网划分方法的基础上,按如下要求完成程序。
1:
命令格式:
ip_testsubnet/maskip_addr
其中,ip_test为程序名;subnet为子网号,mask是一个数值,代表子网掩码连续1的个数,ip_addr是要测试的ip地址。
2:
判断subnet和ip_addr的合法性。
在判断ip地址合法性时要自行编代码,不要使用任何inet函数。
判断时要考虑全面。
3:
判断掩码的合法性。
4:
在ip地址合法的前提下,判断ip_addr是否属于子网subnet。
5:
输出命令行中的ip是否合法,掩码是否合法,以及ip_addr是否属于子网subnet.
三.实验环境(软件、硬件及条件)
1.软件
操作系统:
Windowsxp(WindowsNT以上版本皆可)
编程环境:
MicrosoftVisualStudio2008(兼容MSVS2005,亦可使用等)
编程语言:
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.主机寻址规则
a、主机标识在同一网络内必须是唯一的。
b、主机标识的各个位不能都为“1”,如果所有位都为“1”,则该机地址是广播地址,而非主机的地址。
c、主机标识的各个位不能都为“0”,如果各个位都为“0”,则表示“只有这个网络”,而这个网络上没有任何主机。
3.确定子网掩码数
用于子网掩码的位数决定于可能的子网数目和每个子网的主机数目。
在定义子网掩码前,必须弄清楚本来使用的子网数和主机数目。
定义子网掩码的步骤为:
a、确定哪些组地址归我们使用。
比如我们申请到的网络号为“128B类IP地址,网络标识为“128.73”,主机标识为“”。
b、根据我们现在所需的子网数以及将来可能扩充到的子网数,用宿主机的一些位来定义子网掩码。
比如我们现在需要12个子网,将来可能需要16个。
用第三个字节的前四位确定子网掩码。
前四位都置为“1”,即第三个字节为“,这个数我们暂且称作新的二进制子网掩码。
c、把对应初始网络的各个位都置为“1”,即前两个字节都置为“1”,第四个字节都置为“0”
d、把这个数转化为间断十进制形式为:
“.240.0”这个数为该网络的子网掩码。
掩码的标注
A、无子网的标注法
B、有子网的标注法
有子网时,一定要二者配对出现。
以C类地址为例。
IP地址中的前3个字节表示网络号,后一个字节既表明子网号,又说明主机号,还说明两个IP地址是否属于一个网段。
如果属于同一网络区间,这两个地址间的信息交换就不通过路由器。
如果不属同一网络区间,也就是子网号不同,两个地址的信息交换就要通过路由器进行。
例如:
假设maskwe为27,;2
Part2具体实现
通过以上的原理,我们就知道了在检验IP地址和子网检验时应该明确的问题,关键的两点就是把输入的IP分解成各段,然后判断子网号,掩码和ip地址的基本格式是否合法,
其次:
如果三者的基本格式都合法,才调用断定,ip地址是否为子网成员,的函数。
该函数同时判别子网号与掩码是否匹配,子网号为全0或全1,主机号为全0、全1。
1.实现流程
2.编程
本部分的编程的主要目的是算法的实现,主要的方法是C++中字符串处理。
(1)类设计
a.属性
charip[15];法
构造函数,析构函数:
•ipTest(char*,char*);取参数
•2.简单判断参数格式(长度)
•3.若是正常参数,实例化ipTest类
•4.调用主判断函数voidAllJudgment()判断
•5.输出结果
(3)程序流程
(4)头文件
#include
#include<>
#include<>
#include<>
#include<>
#include<>
usingnamespacestd;
五.实验分析及测试
本部分测试了正常输入和非法输入时,程序对输入的判断,编程的环境为VS2008,在解决方案文件夹下面的Debug文件夹里面生成可执行文件;运行MS-DOS,进入Debug文件夹进行测试。
1.算法正确性检测
(1)用正确格式和合法的数据的输入,测试Mask和IP的匹配
Mask:
15和16
结果截图:
(2)用正确格式和合法的数据的输入,测试主网和子网的匹配
Mask:
18
所以可知:
00101100
2位相于,得:
00
M00000000
2位相于,得:
01
01110001
结果为不匹配。
截图:
00101100
2位相于,得:
00
M00000000
2位相于,得:
00
00110001
结果为匹配。
截图:
(3)补充说明:
ii)考虑
(2)
2.输入合法性测试
本实验程序规定输入的标准参数输入,其中:
X为0-255的十进制整数,mask为0-32的十进制整数,两个IP地址中间用空格分开,IP地址的为4段,每一段都用“.”分开,IP地址中允许出现空格或其他字符
(1)输入的IP地址中含有非法字符
测试数据:
a2
子网IP:
12e
Mask:
1h
结果截图:
(2)输入的IP地址段数不正确
测试数据:
主网IP:
128..
子网IP:
.
Mask:
18
结果截图:
(3)没有输入mask
.11
结果截图:
(4)输入mask超出合法范围
Mask:
35
结果截图:
(5)输入IP超出合法范围
Mask:
25
结果截图:
(6)特殊的IP地址
测试数据:
主网IP:
0.0.0.0
Mask:
0
结果截图:
测试数据:
主网IP:
0.0.0.0
Mask:
0
结果截图:
六.实验结论
本实验根据现在通用的IP地址分配使用规则,设计实验算法,运用C++字符转函数处理,程序实现了基本要求的功能,考虑到了多方面的因素;另一方面,设计之初的思路把此程序定位在接口工具程序,所以省略掉UI的设计,考虑到了扩展性的方面需要,程序提供简单、方便的接口和较为简单参数,方便扩展使用。
仍存在的问题:
数据结构的设计不够清晰简练和方便使用,可读性不太好;主函数流程存在一定的问题,理路不是很清晰,主要是类的各个方法的设计没有总体考虑,设计之初没有考虑,在需要时才加,导致程序结构有点乱,不易阅读和检查。
七.附录源代码
说明:
源文件语言:
C++
文件数:
1
源文件名:
#include
#include<>
#include<>
#include<>
#include<>
#include<>
usingnamespacestd;
;
char*token,*dot[4];
intiplen=0;
token=strtok(chaddr,ch);
while(token!
=NULL)
{
dot[iplen]=token;
addr[iplen]=atoi(dot[iplen]);;
charip_one[18];
strcpy(ip_one,ip);
char*token,*dot[4];
intiplen=0;
是否正确**********************/
intj,t=0;
for(j=0;j<=strlen(ip);j++)
{
if(ip[j]=='.')
{
t++;
}
}
if(t!
=3)
{
cout<<"地址"<"<returnfalse;
}
/************************判断地址是否含有非法字符,每段地址数值溢出**********************/
inti;
for(i=0;i{
if(!
NoIllegalChar(dot[i])||atoi(dot[i])>255)
{
if(!
NoIllegalChar(dot[i]))//判断含有非法字符
cout<<"地址"<"<if(atoi(dot[i])>255)//判断数值溢出
cout<<"地址"<"<returnfalse;
}
}
/*****************判断全或全的情况**************************/
intflag=1;//首先设置为非法,即全
for(i=0;i{
if(atoi(dot[i])!
=0)
{
//含有非的字段
flag=0;
}
}
if(flag==1)
{
cout<<"地址"<"<returnfalse;
}
flag=1;//首先设置为非法,即全
for(i=0;i{
if(atoi(dot[i])!
=255)
{
flag=0;
}
}
if(flag==1)
{
cout<<"地址"<"<returnfalse;
}
/**************以下判断ip地址主机号**********************/
intj1=0,j2;
//if(ip==ip_Temp)
{
//首先判断ip是哪类地址
if(atoi(dot[0])>0&&atoi(dot[0])<127)//A类ip地址
{
j1=1;//直接从开始
}
if(atoi(dot[0])==127)//为的特殊号
{
cout<<"ip地址"<error!
"<returnfalse;
}
if(atoi(dot[0])>=128&&atoi(dot[0])<=191)//B类ip地址
{
j1=2;
}
if(atoi(dot[0])>=192&&atoi(dot[0])<=223)//C类ip地址
{
j1=3;
}
if(atoi(dot[0])>223&&atoi(dot[0])<255)
{
cout<<"请重新输入ip地址"<"<returnfalse;
}
/*
if(atoi(dot[0])==255)
{
cout<<"ip地址"<"<returnfalse;
}
*/
j2=j1;//j1用于判断全情况,j1用于判断全情况的起始下标
intflag=1;//首先设置为非法,即主机号全
for(i=j1;i{
if(atoi(dot[i])!
=0)
{
flag=0;
}
}
if(flag==1)
{
cout<<"ip地址"<"<returnfalse;
}
flag=1;//首先设置为非法,即全
for(i=j2;i{
if(atoi(dot[i])!
=255)
{
flag=0;
}
}
if(flag==1)
{
cout<<"ip地址"<"<returnfalse;
}
}
returntrue;
}
//判断子网号subnet是否合法
boolipTest:
:
subnetIsValid(char*subnet)
{
if(!
ipIsValid(subnet))//调用判断Ip的函数ipIsValid()进行判断
{
returnfalse;
}
returntrue;
}
//判断ip是否为子网成员,并输出判断结果
voidipTest:
:
print()
{
charsubnet_one[15],ip_one[15];
intnbip[4],nbsubnet[4],i;
strcpy(subnet_one,subnet);//把subnet地址复制给subnet_one
strcpy(ip_one,ip);//把ipt地址复制给ip_one
//split()函数把字符型的地址转换为四段int型的地址
split(subnet_one,nbsubnet);//用subnet_one而非subnet是为了保护subnet地址不被破坏
split(ip_one,nbip);
for(i=0;i<4;i++)
{
nbip[i]=toBinary(nbip[i]);//将分离出来的十进制转换为二进制
nbsubnet[i]=toBinary(nbsubnet[i]);
}
char*cbip=newchar[33];
char*cbsubnet=newchar[33];
cbip=toString(nbip);//将二进制数组转换为位的二进制字符指针
cbsubnet=toString(nbsubnet);
for(i=0;i{
if(cbip[i]!
=cbsubnet[i])
{
cout<"<//system("pause");
return;
}
}
cout<"<//system("pause");
}
//十进制int型数据转换为二进制int型数据
intipTest:
:
toBinary(inta)
{
//将十进制数转换为二进制数
if(a/2==0)returna%2;
returna%2+toBinary(a/2)*10;//递归调用
}
//把二进制int型数据转换为一个整体的二进制字符型数据
char*ipTest:
:
toString(int*a)
{
//将二进制的数值数组转换个字符长的字符指针
char*temp=newchar[33];inti;
boolflag=false;
char*eight=newchar(),*seven=newchar(),*six=newchar(),*five=newchar(),*four=newchar(),
*three=newchar(),*two=newchar(),*one=newchar();
for(i=0;i<4;i++)
{
//char*itoa(intvalue,char*string,intradix)将整数value转换成字符串存入string,radix为转换时所用基数
itoa(a[i]/1000000%10,seven,10);
itoa(a[i]/100000%10,six,10);//a[i]/100000%10为每段的高第三位二进制整数
itoa(a[i]/10000%10,five,10);
itoa(a[i]/1000%10,four,10);
itoa(a[i]/100%10,three,10);
itoa(a[i]/10%10,two,10);
itoa(a[i]%10,one,10);
if(flag==true)
{
strcat(temp,eight);
}
else
{
//第一次循环时,执行此步骤;同时置flag=true保证以后循环不执行此步
strcpy(temp,eight);//第一次循环的第一次传递用连接函数
flag=true;
}
strcat(temp,seven);strcat(temp,six);strcat(temp,five);
strcat(temp,four);
strcat(temp,three);strcat(temp,two);strcat(temp,one);
}
returntemp;
}