计算机网络技术课程设计报告.docx
《计算机网络技术课程设计报告.docx》由会员分享,可在线阅读,更多相关《计算机网络技术课程设计报告.docx(14页珍藏版)》请在冰豆网上搜索。
计算机网络技术课程设计报告
计算机网络技术课程设计报告
班级:
姓名:
学号:
第一题计算校验和
1.1课程设计的目的
网络上的信号最终都是通过物理传输线路进行传输的,如果高层没有采用差错控制,那么物理层传输的数据信号是可能有差错的。
为了保证数据的正确性,在物理层的基础上设计了数据链路层。
设计数据链路层的主要作用就是在原始的、有差错的物理传输线路的基础上,采用差错检测、差错控制与流量控制等方法,将有差错的物理线路改进成逻辑上无差错的数据链路,以向网络层提供高质量的服务。
本课程设计主要通过一个简单例子使学生了解网络协议中校验和的计算过程,以及设置校验和的作用。
目前,进行差错检测和差错控制的主要方法是:
在需要传输的数据分组后面加上一定的冗余信息,这样的冗余信息通常都是通过对所发送数据应用某种算法进行计算而得到的。
数据的接收方在接收到数据后进行同样的计算再与收到的冗余信息进行比较,如果结果不同就说明出现了差错,此时可以要求发送方重传该数组数据,以此达到数据准确性的目的。
在普遍使用的网络协议中都设置了校验和项以保存这些冗余信息,例如Ipv4、ICMPv4、IGMPv4、ICMPv6、UDP和TCP等等。
计算校验和的算法称为国际校验和算法,简单来说,就是把被校验的数据按16位进行累加,然后取反码。
若数据字节长度为奇数,则在这数据尾部补一个字节的0以凑成偶数。
关于计算校验和算法更详细的信息请参考RFC1071。
1.2课程设计要求
根据前面介绍的算法,编制程序为给定数据计算校验和。
1)以命令形式运行:
check_suminfile
其中check_sum为程序名,infile为输入数据文件名。
2)输出:
数据文件的校验和。
程序:
#include
#include
voidmain(intargc,char*argv[])//指针数组作为主函数参数,用于函数输入
{
//定义并初始化变量
FILE*fp;
charch;
unsignedcharcharl,charh;
unsignedintcount=0,checksum=0,chr=0;
unsignedlongintsum=0;
//打开文件argv[l]
if((fp=fopen(argv[1],"r"))==NULL)
{
printf("\n\nFilecan'tbeopened");
exit
(1);
}
printf("\n\nthetypeofoutput:
data---sum\n\n");
//从txt文件读取字符,并进行数据处理
while
(1)
{
if((ch=fgetc(fp))!
=EOF)
{
count++;
if(ch!
='')
{
if(count%12==0)
printf("\n");
//将字符转换为相应整形变量
if(ch>='0'&&ch<='9')
ch-='0';
else
if(ch>='a'&&ch<='f')
ch=ch-'a'+10;
else
if(ch>='A'&&ch<='F')
ch=ch-'A'+10;
//计算8字节数的累加值,将奇数位累加到长整形sum的15~8位,偶数位累加到低8~0位
//这样就避免了数据个数为奇偶的处理操作
if(count%2==1)
charh=ch<<4;
else
{
charl=ch&0x0f;
chr=charh|charl;
if(count%4==2)
sum+=chr<<8;
else
if(count%4==0)
sum+=chr;
printf("%x--%lx",chr,sum);
}
}
else
{
count--;
}
}
else
{
break;
}
}
//将sum由32位折合成16位
if(sum>>16)
checksum=(long)((sum>>16)+(long)(sum&0x0000ffff));
else
checksum=sum;
checksum=checksum&0x0000ffff;
//结果输出
printf("\n\nsum:
%lx---checksum:
%x",sum,checksum);
printf("\n\nsource:
argc=%d,\targv=%s\n",argc,argv[1]);
fclose(fp);
}
输入:
1452967445781345
运行结果:
第二题IP地址的合法性及子网判断
2.1课程设计目的
本设计要求编写程序,判断一个IP地址是否合法,并判断该地址是否属于一个给定子网。
从而考察读者是否对IP地址概念及其子网划分有非常清楚的认识。
2.2课程设计要求
在掌握IP地址表示方法及子网划分方法的基础上,按如下要求完成程序。
1)命令行格式:
ip_testsubnet/maskip_addr
其中,ip_test为程序名;subnet为子网号;mask是一个数值,代表子网掩码连续1的个数;ip_addr是要测试的IP地址。
例如,要测试的IP地址为202.113.16.10,子网号为为202.113.16.0,子网掩码为255.255.255.0,则命令行为ip_test202.113.16.0、24202.113.16.10.(因为255.255.255.0是连续的24个1,所以用24表示。
)
2)判断subnet和ip_addr的合法性。
在判断IP地址合法性时要自行编写代码,不要使用任何inet函数。
判断时要考虑全面,比如以下ip地址均不合法:
123..2.1
123.23¥.2.1
123.2345.2.1
123.23.45.2.1
3)判断掩码的合法性。
4)在IP地址合法的前提下,判断ip_addr是否属于子网subnet.
5)输出命令行中的ip是否合法,掩码是否合法(可适当给出不合法原因)以及ip_addr是否属于子网subnet。
A类,B类与C类IP地址中主机号权1的地址chengweizhijieguangbo地址,用来使路由器将一个分组以广播方式发送给特定网络上的所有主机。
直接广播地址只能作为分组中的目的地址。
物理网络采用的使点-点传输方式,分组广播需要通过软件来实现。
网络号
主机号全1
2)受限广播地址
网络号与主机号的32位全为1的地址为受限广播地址,用来将一个分组以广播方式发送给本网的所有主机。
本网的所有主机将接受该分组,路由器则阻挡该分组通过。
全1
3)“这个网络上的这台主机”地址
全0
4)”这个网络上的特定主机”
主机或路由器向本网络上的某个特定的主机发送分组,网络号部分为全0,主机号为确定的值。
这样的分组被限制在本网络内部。
网络号全0
主机号
5)回送地址
回送地址用于网络软件测试和本地进程间通信。
TCP/IP协议规定网络号为127的分组不能出现在任何网络上;主机和路由器不能为该地址广播任何寻址信息。
127
任意值(通常取1)
程序:
#include
#include
#include
#include
#include
#include
//类结构
classipTest{
charip[15];
charsubnetPlusMask[18];
charsubnet[18];
charTempIp[15];
charTempSub[18];
intmask;
boolmaskIsValid;
public:
ipTest(char*,char*);
ipTest(){};
boolNoIllegalChar(char*);//非法字符的判断
boolipIsValid(char*);//判断IP地址是否合法
boolsubnetIsValid(char*);//判断子网号是否合法
voidbelong();//判断IP是否为子网成员
print();
}
;
//主函数
voidmain(intargc,char*argv[]){
if(argc!
=3){//判断参数格式是否正确
cout<<"error"<ip_testsubnet/maskip"<return;
}
else{
if(strlen(argv[1])>18){//先判断最简单的错误,长度是否超出
cout<<"subnet/maskistoolong";
return;
}
if(strlen(argv[2])>15){
cout<<"ipistoolong";
return;
}
ipTesttest(argv[1],argv[2]);//实例化ipTest类
test.print();//完成相应判别并输出结果
}
}
//构造函数
ipTest:
:
ipTest(char*subnetPlusMask,char*ip){
maskIsValid=true;
chartemp[2];
//把'/'前的字符复制到subnet字符数组中
intsmLen=strlen(subnetPlusMask);
for(inti=0;i='/';i++){
this->subnet[i]=subnetPlusMask[i];
this->TempSub[i]=subnetPlusMask[i];
}
subnet[i]='\0';
TempSub[i]='\0';
if(i<=smLen-2){//初始化mask和maskIsValid
if(i==smLen-2){
temp[0]=subnetPlusMask[i+1];
if(!
isdigit(temp[0]))
maskIsValid=false;
}
elseif(i==smLen-3){
temp[0]=subnetPlusMask[i+1];
temp[1]=subnetPlusMask[i+2];
if(!
(isdigit(temp[0])&&isdigit(temp[1])))
maskIsValid=false;
}
mask=atoi(temp);
if(mask<0||mask>32)
maskIsValid=false;
}
else//用十进制表示的掩码中的1的个数只能是一位数或两位数
maskIsValid=false;
strcpy(this->subnetPlusMask,subnetPlusMask);//给subnetPlusMask赋值
strcpy(this->ip,ip);//给IP赋值
strcpy(this->TempIp,ip);
}
//调用判别函数,并输出结果
ipTest:
:
print(){
boolsubIsV=subnetIsValid(TempSub);
boolipIsV=ipIsValid(TempIp);
if(!
subIsV)//subnet非法
cout<<"subnetisinvalid!
"<else
cout<<"validsubnet:
"<if(!
maskIsValid)//mask非法
cout<<"maskisinvalid!
"<else
cout<<"validmask:
"<if(!
ipIsV)//ip非法
cout<<"ipisinvalid!
"<else
cout<<"validip:
"<//判断ip是否belongsubnet
if(subIsV&&ipIsV&&maskIsValid)
belong();
}
//子函数,判断输入是否含有非数字字符
boolipTest:
:
NoIllegalChar(char*ch){
unsignedinti,k=0;
for(i=0;iif(isdigit(*(ch+i))==0){//判断每一位是否为数字字符
returnfalse;
}
}
returntrue;//若不含有非数字字符则返回true
}
//判断IP地址是否合法
boolipTest:
:
ipIsValid(char*ip){
charch[]=".";//分隔符
char*token,*dot[4];
intiplen=0;
token=strtok(ip,ch);//以"."标志将IP字符串按字节分开
while(token!
=NULL){//循环进行,直到结束
dot[iplen]=token;//将分开的每段赋值给dot
iplen++;
token=strtok(NULL,ch);
}
if(iplen!
=4)
returnfalse;//段数不对
for(inti=0;i<4;i++){
if(!
NoIllegalChar(dot[i])||atoi(dot[i])>255)//有非法字符或某段值非法
returnfalse;
}
returntrue;
}
//判断子网号是否合法
boolipTest:
:
subnetIsValid(char*subnet){
if(!
ipIsValid(subnet))//调用判别IP地址合法性的函数
returnfalse;
returntrue;
}
//判断IP是否为子网成员,判断子网号与掩码是否匹配,以及子网号、主机号全0全1问题
voidipTest:
:
belong(){
intsubLen=strlen(subnet);
intipLen=strlen(ip);
unsignedintiIPA,iSubA,iMask;
unsignedcharsubA[4],ipA[4];
chartemp[3];
inti,j,t=0;
for(i=0,j=0;iif(subnet[i]!
='.')
temp[j++]=subnet[i];//temp数组中放'.'间的串
else{
subA[3-t]=atoi(temp);//subA数组中放'.'间的数据
j=0;
t++;
temp[0]=temp[1]=temp[2]='\0';
}
}
subA[0]=atoi(temp);
temp[0]=temp[1]=temp[2]='\0';
iSubA=*(unsignedint*)subA;//iSubA中放subnet中'.'除外的串对应的数
for(i=0,j=0,t=0;iif(ip[i]!
='.')
temp[j++]=ip[i];
else{
ipA[3-t]=atoi(temp);
j=0;
t++;
temp[0]=temp[1]=temp[2]='\0';
}
}
ipA[0]=atoi(temp);
iIPA=*(unsignedint*)ipA;//iIPA中放IP中'.'除外的串对应的数
iMask=0xffffffff;
iMask<<=(32-mask);//获得掩码
if((iSubA|iMask)!
=iMask){//说明sub与mask不匹配
cout<<"子网号与掩码不匹配,error!
"<return;
}
if((iSubA^iMask)==0){//说明子网号全1
cout<<"子网号全1,error!
"<return;
}
if((iSubA&iMask)==0){//说明子网号全0
cout<<"子网号全0,error!
"<return;
}
if((iSubA)==(iIPA&iMask)){//IP和掩码与,结果和子网号进行比较
if((iIPA|iMask)==iMask){//说明主机号全0
cout<<"主机号全0,error!
"<return;
}
if((iIPA|iMask)==0xffffffff){//说明主机号全1
cout<<"主机号全1,error!
"<return;
}
//ip属于subnet
cout<<""<return;
}
//ip不属于subnet
else
cout<<""<}输入:
ipconfig
ip_test10.3.4.0/2410.3.4.137
ip_test10.3.4.0/3210.3.4.137
ip_test10.3.4.1/2410.3.4.137
运行结果:
心得:
回顾起此次课程设计,至今我仍感慨颇多,的确,自从拿到题目到完成整个编程,从理论到实践,在整整一个星期的日子里,可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
在设计的过程中遇到问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体……通过这次课程设计之后,一定把以前所学过的知识重新温故。
这次课程设计终于顺利完成了,在设计中遇到了很多编程问题,最后在谢老师的辛勤指导下,终于游逆而解。
同时,对给过我帮助的所有同学和各位指导老师表示感谢!