1计算机网络课程设计报告2012年7月2日2目录1.CRC检验码…………………………………………………………31.1题目描述…………………………………………………………31.2需求分析…………………………………………………………31.3算法设计…………………………………………………………31.4功能实现…………………………………………………………62.RIP协议………………………………………………………………72.1题目描述…………………………………………………………72.2需求分析…………………………………………………………72.3算法设计…………………………………………………………82.4功能实现…………………………………………………………133.滑动窗口……………………………………………………………153.1题目描述…………………………………………………………153.2需求分析…………………………………………………………153.3算法设计…………………………………………………………163.4功能实现…………………………………………………………224.课程设计总结………………………………………………………245.重要程序清单………………………………………………………251.CRC检验码31.1题目描述课本P105页3-07:要发送的数据为1101011011,采用CRC的生成多项式是P(C)=X^4+X+1,试为该数据添加CRC码,并验证他的正确性,改动CRC码最后一位,验证他的正确性。1.2需求分析CRC循环冗余检验是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。上题即是要求编程实现CRC算法并利用其验证发送数据的正确性。循环冗余校验码(CRC)的基本原理是:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码又叫(N,K)码。对于一个给定的(N,K)码,可以证明存在一个最高次幂为N-K=R的多项式G(x)。根据G(x)可以生成K位信息的校验码,而G(x)叫做这个CRC码的生成多项式。校验码的具体生成过程为:假设发送信息用信息多项式C(X)表示,将C(x)左移R位,则可表示成C(x)*2的R次方,这样C(x)的右边就会空出R位,这就是校验码的位置。通过C(x)*2的R次方除以生成多项式G(x)得到的余数就是校验码。1.3算法设计1.3.1CRC码的生成步骤1、将x的最高幂次为R的生成多项式G(x)转换成对应的R+1位二进制数。2、将信息码左移R位,相当与对应的信息多项式C(x)*2的R次方3、用生成多项式(二进制数)对信息码做除,得到R位的余数。4、将余数拼到信息码左移后空出的位置,得到完整的CRC码。【例如】题给的生成多项式是P(C)=X^4+X+1。5位的原始报文为1101011011,求编码后的报文。解:1、将生成多项式P(C)=X^4+X+1转换成对应的二进制除数10011。2、此题生成多项式有5位(R+1),要把原始报文P(x)左移4(R)位变成110101101100003、用生成多项式对应的二进制数对左移4位后的原始报文进行除运算。1.3.2生成步骤分析4步骤1中的转换过程可以由用户完成,即程序可以只提供二进制序列的输入(这样方便实现)。1.3.3算法具体实现1)核心函数CRC定义一个函数名为stringCRC(stringdata,stringdiv)的函数,其参数分别为发送数据data和除数div(都有用户输入,由主函数传值)2)函数分布实现strings1,s2,temp;intlen;len=div.length();//下面的for循环式补0操作,相当于上述步骤2for(inti=0;ilen-1;i++)data.append(0);//下面是当除数data长度大于等于除数时做循环异或操作的过程while(data.length()=div.length()){s2=;//中间变量,用来村粗每次异或的结果s1=data.substr(0,len);//求子串data=data.substr(len,data.length()-len);//下面是具体的一对一的异或运算操作for(inti=0;i(int)div.length();i++){if(s1[i]==div[i])//相同s2.append(0);elses2.append(1);//相异}//将s2前面0去掉,因为前面的0无意义,去掉后再继续下次异或while(s2.length()!=0)5{temp=s2[0];if(temp.compare(0)!=0)break;s2=s2.substr(1,s2.length()-1);}data=s2.append(data);//让data时刻更新}returndata;//即为校验码}3)crc补0操作CRC()函数返回的crc序列已经将其前面的0去除了,所以在主函数中接受到crc时,先判断长度够不够R,不够R说明前面需要把0还原,操作如下:if(crc.length()!=DIV.length())//前面补0操作{for(i=0;iDIV.length()-1-crc.length();i++)FCS.append(0);FCS.append(crc);}4)实际发送函数ActSend()这里,我将最后发送的数据序列(原数据+CRC码)在一个函数中实现如下:stringActSend()//实际发送序列{stringsend=;send=DATA;send.append(FCS);returnsend;}5)接收方检验收到的数据正确与否crc=CRC(DATA,DIV);if(crc!=)6coutYendl;elsecoutNendl;这里的DATA为传送过程中改变了数据,DIV依然是原除数。1.4功能实现1.4.1题给要求结果如下用户输入要发送的序列1101011011和除数10011,程序给出CRC检验序列并给出实际应发送数据如上。正确与否判断,当传送过程中最后一个两个以及三个1变为0,程序检测情况如下:测试其它数据(课本68页)如下:72.RIP协议2.1题目描述课本P126页图4-16,加载RIP协议,得到R1,R2,R3的路由表。2.2需求分析2.2.1根据课本图4-16,作出模拟图如下:并设路由器R1、R2、R3的初始路由表如下:2.2.1RIP协议简介RIP协议的全称是一种内部网关协议(IGP),是一种动态路由选择,用于一个自治系统(AS)内的路由信息的传递。RIP协议是基于距离矢量算法8(DistanceVectorAlgorithms)的,它使用“跳数”,即metric来衡量到达目标地址的路由距离。这种协议的路由器只关心自己周围的世界,只与自己相邻的路由器交换信息,范围限制在15跳(15度)之内,再远,它就不关心了。在路由实现时,RIP作为一个系统长驻进程(daemon)而存在于路由器中,负责从网络系统的其它路由器接收路由信息,从而对本地IP层路由表作动态的维护,保证IP层发送报文时选择正确的路由。同时负责广播本路由器的路由信息,通知相邻路由器作相应的修改。2.2.3距离向量算法1、对地址X的相邻的路由器发来的RIP报文,先修改此报文中所有的项目;把“下一条”字段中的地址都改为X,并把所有距离都加1。2、对修改后的报文的每一个项目,进行一下步骤:若原路由器没有该目的网络,就直接加载路由表中;不然,再看下一条路由器地址,若是X,则用收到的项目替换原来的;若下一条地址不同,收到的项目的距离小于原来的距离,则替换,否则什么都不用做。3、若3分钟没有收到相邻路由器的更新路由表,则把此相邻路由器记为补课达的路由器,即把距离设为164、返回2.3算法设计2.3.1改变函数的实现根据距离向量算法第1步,我知道首先需要将发来的路由表作更改,更改函数及解释如下:voidRoute::change(inta){listTablepa;//定义一个中间容器,用来存储改变后的路由信息stringroute;//下面的几个条件判断用来识别当前传进来的是哪个路由表信息if(a==2){pa=piece2;route=route2;}elseif(a==1)9{pa=piece1;route=route1;}else{pa=piece3;route=route3;}//下面的for循环式是具体的更改过程for(listTable::iteratorit=pa.begin();it!=pa.end();it++){((*it).distance)++;(*it).next_stop=route;}cout改变近邻路由表:endl;recover=pa;show(pa);}2.3.2更新函数的实现更新函数是距离向量算法的核心部分,我将函数命名为update,定义在类Route中,函数的两个参数a,b分别用来表示哪个路由器要修改以及哪个路由器发送信息出来。下面分三个模块解释我的函数实现:voidRoute::update(inta,intb){intcount=0;//计数器,用来表示id2是否出现与id1中listTablepa,pb;//第一模块,根据参数判断发出信息的路由器和当前需要更新的路由器if(a==1&&b==2)//R2发送RIPpa=piece1;elseif(a==3&&b==2)pa=piece3;elseif(a==2&&b==1)//R1发送RIPpa=piece2;10elseif(a==3&&b==1)pa=piece3;elseif(a==1&&b==3)//R3发送RIPpa=piece1;elseif(a==2&&b==3)pa=piece2;//因为在change()函数中已经将刚刚改变的路由信息放在recover中,所以这里只要将recover信息赋给pb即可pb=recover;listTable::iteratorit1=pa.begin();listTable::iteratorit2=pb.begin();//第二模块很重要////////下面的两个for循环就是一行行更新pa路由表信息的过程,具体算法的思路即是距离向量算法的第2步。特殊步骤的标示见下面程序for(;it2!=pb.end();it2++)//对于pb路由表的每一行{for(it1=pa.begin();it1!=pa.end();it1++)//查找pa的每一行{if((*it1).destination_id==(*it2).destination_id){count++;if(((*it1).next_stop)==((*it2).next_stop))//下一跳相同时,一定更新{(*it1).distance=(*it2).distance;(*it1).next_stop=(*it2).next_stop;}if(((*it1).next_stop!=(*it2).next_stop)&&((*it1).distance(*it2).distance))//下一跳不相同时,选择较小的距离{11(*it1).distance=(*it2).distance+1;(*it1).next_stop=(*it2).next_stop;}}}if(count==0)//说明该路由不在piece1中pa.push_back(*it2);count=0;}//第三模块,即是将更新后的pa赋值到具体需要改变的路由表容器中if(a==1)piece1=pa;elseif(a==2)piece2=pa;elsepiece3=pa;show(pa);}2.3.3路由表收敛题给示例中只有三个路由表,其之间的相邻关系已经一目了然,所以我在程序中就没有将路由表的邻近关系存储起来,而是直接通过下面的固定操作实现:分三种情况,R2发送路由信息,R1、R3更新;R1发送路由信息R2更