RIP协议设计 毕业课程设计报告包含源代码.docx
- 文档编号:29457826
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:35
- 大小:101.58KB
RIP协议设计 毕业课程设计报告包含源代码.docx
《RIP协议设计 毕业课程设计报告包含源代码.docx》由会员分享,可在线阅读,更多相关《RIP协议设计 毕业课程设计报告包含源代码.docx(35页珍藏版)》请在冰豆网上搜索。
RIP协议设计毕业课程设计报告包含源代码
(此文档为word格式,下载后您可任意编辑修改!
)
网络程序设计
课程设计报告
题目RIP协议设计
专业及班级网络工程1101班
学号
姓名
日期2012年7月3日
一、课程设计目的
了解RIP协议的原理和应用等相关知识,通过距离矢量算法来实现最短传输路径的路由选择。
通过本次课程设计,可以对RIP协议的工作原理和实现机制,路由表的建立和路由信息的更新等有更直观和清晰的认识。
程序运行后能与路由器的RIP协议程序正确通信。
查阅相关RFC。
提供配置命令,程序运行后能动态设置协议参数。
收到的数据先放入循环队列,再从队列中取出依次处理。
使用定时器处理超时事件。
二、设计与实现
2.1RIP协议的报文格式分析
对于RIP报文有两种版本的格式,Version1和Version2。
两种报文稍有不同,如所示分别为RIPv1和RIPV2:
命令
版本
全零
地址族
全零
IP地址
全零
全零
度量值
前20个字节的重复
命令
版本
路由选择
地址族
路径标签
IP地址
子网掩码
下一个站点的IP地址
度量值
前20个字节的重复
RIP报文中至多可以出现25个AFI、互联网络地址和度量域。
这样允许使用一个RIP报文来更新一个路由器中的多个路由表项。
包含多个路由表项的RIP报文只是简单地重复从AFI到度量域的结构,其中包括所有的零域。
图表2显示了路由信息域中只带一个目的地的RIP报文。
1字节命令
1字节版本
2字节0域
2字节
AFI
2字节
0域
4字节
网络地
址
4字节
0域
4字节
0域
4字节
度量
图表2
图表3具有两个表项的RIP报文
1字节
命令
1字节
版本
2字节
0域
两字节
AFI
2字节
0域
4字节
网络地址
4字节
0域
4字节
0域
4字节
度量
4字节
网络
地址
4字节
0域
4字节
0域
4字节
度量
图表3
地址域可以既包括发送者的地址也包括发送者路由表中的一系列IP地址。
请求报文含有一个表项并包括请求者的地址。
应答报文可以包括至多25个RIP路由表项。
2.2RIP的工作原理
RIP协议是矢量距离算法在局域网上的直接实现,RIP将协议的参加者分为主动机和被动机两种。
主动机主动地向外广播路径刷新报文,被动机被动地接受路径刷新报文。
一般情况下,网关作主动机,主机作被动机。
RIP规定,网关每30秒向外广播一个报文,报文信息来自本地路由表。
RIP的度量是基于跳数(hops count)的,每经过一台路由器,路径的跳数加一。
如此一来,跳数越多,路径就越长,RIP算法会优先选择跳数少的路径。
RIP支持的最大跳数是15,跳数为16的网络被认为不可达。
对于相同开销路径的处理是采用先入为主的原则。
在具体的应用中,可能会出现这种情况,去往相同网络有若干条相同距离的路径。
在这种情况下,无论哪个网关的路径广播报文先到,就采用谁的路径。
直到该路径失败或被新的更短的路径来代替。
RIP中路由的更新是通过定时广播实现的。
缺省情况下,路由器每隔30秒向与它相连的网络广播自己的路由表,接到广播的路由器将收到的信息添加至自身的路由表中。
每个路由器都如此广播,最终网络上所有的路由器都会得知全部的路由信息。
正常情况下,每30秒路由器就可以收到一次路由信息确认,如果经过180秒,即6个更新周期,一个路由项都没有得到确认,路由器就认为它已失效了。
如果经过240秒,即8个更新周期,路由项仍没有得到确认,它就被从路由表中删除。
上面的30秒,180秒和240秒的延时都是由计时器控制的,它们分别是更新计时器(Update Timer)、无效计时器(Invalid Timer)和刷新计时器(Flush Timer)。
距离向量类的算法容易产生路由循环,RIP是距离向量算法的一种,所以它也不例外。
如果网络上有路由循环,信息就会循环传递,永远不能到达目的地。
如果出现环路,直到路径长度达到16,也就是说要经过210秒(30X7秒)来回,路径回路才能被解除,这就是所谓的慢收敛问题。
是RIP的一个很大的缺陷,为了避免这个问题,RIP等距离矢量算法实现了4个机制:
水平分割(split horizon)
水平分割保证路由器记住每一条路由信息的来源,并且不在收到这条信息的端口上再次发送它。
这是保证不产生路由循环的最基本措施。
毒性逆转(poison reverse)
当一条路径信息变为无效之后,路由器并不立即将它从路由表中删除,而是用16,即不可达的度量值将它广播出去。
这样虽然增加了路由表的大小,但对消除路由循环很有帮助,它可以立即清除相邻路由器之间的任何环路。
触发更新(trigger update)
当路由表发生变化时,更新报文立即广播给相邻的所有路由器,而不是等待30秒的更新周期。
同样,当一个路由器刚启动RIP时,它广播请求报文。
收到此广播的相邻路由器立即应答一个更新报文,而不必等到下一个更新周期。
这样,网络拓扑的变化会最快地在网络上传播开,减少了路由循环产生的可能性。
抑制计时(holddown timer)
一条路由信息无效之后,一段时间内这条路由都处于抑制状态,即在一定时间内不再接收关于同一目的地址的路由更新。
如果,路由器从一个网段上得知一条路径失效,然后,立即在另一个网段上得知这个路由有效。
这个有效的信息往往是不正确的,抑制计时避免了这个问题,而且,当一条链路频繁起停时,抑制计时减少了路由的浮动,增加了网络的稳定性。
即便采用了上面的4种方法,路由循环的问题也不能完全解决,只是得到了最大程度的减少。
一旦路由循环真的出现,路由项的度量值就会出现计数到无穷大(CounttoInfinity)的情况。
这是因为路由信息被循环传递,每传过一个路由器,度量值就加1,一直加到16,路径就成为不可达的了。
RIP选择16作为不可达的度量值是很巧妙的,它既足够的大,保证了多数网络能够正常运行,又足够小,使得计数到无穷大所花费的时间最短。
有些网络是NBMA(Non-BroadcastMultiAccess,非广播多路访问)的,即网络上不允许广播传送数据。
对于这种网络,RIP就不能依赖广播传递路由表了。
解决方法有很多,最简单的是指定邻居(neighbor),即指定将路由表发送给某一台特定的路由器。
2.3主要函数模块说明
2.3.1get_local_ip()
该函数主要是通过gethostname()函数获取本地ip,并将其赋值给local_addr;
2.3.2broadcast_rip_packet()
首先将包转换成网络读取数据的顺序,然后将要广播的ip和协议封装在一个结构体中,从定义的RIP端口520广播出去。
print_rip_packet()-->rp_inverse_hton()-->socket()-->sendto()-->close()
2.3.3timer_routine()
使用线程的pthread_mutex_lock()和pthread_mutex_unlock()对路由表更新模块进行保护,以防资源被更改。
2.3.4receive_rip_packet()
从网络上接受包,并解析结构体过去包的ip,通过520端口获得包,并检查包的格式,然后分析包的命令是请求还是相应给于相应的处理。
socket()-->bind()-->recvfrom()-->rp_inverse_ntoh()-->print_rip_packet()-->check_rip_packet()
2.3.5handle_request()
先检查路由表是否为空,为空则返回错误信息,不为空则返回rip包和路由表。
2.3.6handle_response()返回自身的rip包和路由表。
2.4实现方法
2.4.1包的包装和解析
通过定义structrip_entry、structrip_packet、structroute_entry三个结构体分别对rip和路由表进行包装,然后解析过程则只需通过获取结构体的成员便可得到相应的部分然后进行相应的处理。
2.4.2加锁和解锁过程
应用函数:
update_routing_table()
功能:
通过加锁和解锁使得在更新路由表过程中路由表中的数据不会被其他的线程更改,例如:
打印路由表,处理请求和应答等。
2.5RIP协议的运行过程
网关刚启动时,运行V-D算法,对V-D路由表进行初始化,为每一个和它直接相连的实体建一个表目,并设置目的IP地址,距离为1(这里RIP和V-D略有不同),下一站的IP为0,还要为这个表目设置两个定时器(超时计时器和垃圾收集计时器)。
每隔30秒就向它相邻的实体广播路由表的内容。
相邻的实体收到广播时,在对广播的内容进行细节上的处理之前,对广播的数据报进行检查。
因为广播的内容可能引起路由表的更新,所以这种检查是细致的。
首先检查报文是否来自端口520的UDP数据报,如果不是,则丢弃。
否则看RIP报文的版本号:
如果为0,这个报文就被忽略;如果为1,检查必须为0的字段,如果不为0,忽略该报文;如果大于1,RIP-1对必须为0的字段就不检查。
然后对源IP地址进行检查,看它是否来自直接相连的邻居,如果不是来自直接邻居,则报文被忽略。
如果上面的检查都是有效的,则对广播的内容进行逐项的处理。
看它的度量值是否大于15,如果是则忽略该报文(实际上,如果来自相邻网关的广播,这是不可能的)。
然后检查地址族的内容,如果不为2,则忽略该报文。
然后更新自己的路由表,并为每个表目设置两个计时器,初始化其为0。
就这样所有的网关都每隔30秒向外广播自己的路由表,相邻的网关和主机收到广播后来更新自己的路由表。
直到每个实体的路由表都包含到所有实体的寻径信息。
如果某条路由突然断了,或者是其度量大于15,与其直接相邻的网关采用分割范围或触发更新的方法向外广播该信息,其他的实体在两个计时器溢出的情况下将该路由从路由表中删除。
如果某个网关发现了一条更好的路径,它也向外广播,与该路由相关的每个实体都要更新自己的路由表的内容。
程序流程图:
2.4RIP协议的运行结果
三、设计技巧及体会
这几天的课程设计令我受益匪浅,使我加强了课本的知识。
当然,在课程设计的过程中遇到的困难也是很多的,比如,刚开始做的时候不知道如何下手,在设计过程中遇到看不懂的程序,程序错误连连,如何修改程序,修改出来的程序能否达到设计的要求等等。
在这困难重重的情况下,我们一组始终保持不骄不躁的作风,保持足够的耐心,一步步的查资料,慢慢的修改程序,实在看不懂的就问老师及同学,终于完成了课程设计。
通过本次计算机网络课程设计,我更加充分的理解了课本上的知识,并能够加以扩展,从而应用于实践当中。
总之,通过不懈的努力,我们积极讨论,在愉快中很好的完成了自己的任务,。
在课程设计期间也让自己学会了很多知识掌握的必要性,学会和同伴的协作能力,对自己起到了很好的锻炼作用。
通过这次课程设计让我们更加全面的了解了RIP协议的工作原理和实现机制,同时使我够更好地掌握了网络编程的开发流程,增强了实践能力,进一步提高解决实际问题的能力。
选路信息协议RIP使用矢量距离算法来传播路由。
距离向量类的算法容易产生路由循环,RIP是距离向量算法的一种,所以它也不例外。
为了解决环路问题,RIP应用了诸如设置最大跳数,水平划分法,路由超时和毒性逆转等技巧。
但即便采用了上面的方法,路由循环的问题也不能完全解决,只是得到了最大程度的减少。
另外RIP协议也存在着一些很重要的缺陷,主要有以下几点:
(1)过于简单,以跳数为依据计算度量值,经常得出非最优路由。
(2)度量值以16为限,不适合大的网络。
(3)安全性差,接受来自任何设备的路由更新。
无密码验证机制,默认接受任何地方任何设备的路由更行。
不能防止恶意的rip欺骗。
(4)不支持无类ip地址和VLSM
(5)收敛性差,时间经常大于5分钟。
(6)消耗带宽很大。
完整的复制路由表,把自己的路由表复制给所有邻居,尤其在低速广域网链路上更以显式的全量更新。
四、附录
参考文献
【1】谢希仁,《计算机网络(第五版)》.电子工业出版社,2008
【2】闵应骅,计算机网络路由研究综述[J];计算机学报;2003年06期
【3】苏湘玉,路由信息协议及重发布技术研究与实现;中国人民解放军国防科学技术大学;2002年
【4】RFC1058;RFC1388;RFC2453
源代码:
头文件RIP.h
#ifndef_MYRIP_H
#define_MYRIP_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineRIP_VERSION1
#defineRIP_REQUEST1
#defineRIP_RESPONSE2
#defineRIP_INFINITY16
#defineRIP_MAX_ENTRY25
#defineRIP_MAX_PACKET504
#defineRIP_PACKET_HEAD4
#defineRIP_PORT520
#defineROUTE_MAX_ENTRY256
#defineLOCAL_ROUTE_ENTRY10
#defineROUTE_VALID1
#defineROUTE_UNVALID0
#defineRIP_CHECK_OK1
#defineRIP_CHECK_FAIL0
#defineBROADCAST_INTERVAL10
#defineCLOCK_TIMEOUT15
#defineGARBAGE_REMOVE_TIMEOUT25
structrip_entry//¶šÒåÁËRIP±šÎÄÄڵĵ¥žö·ÓÉ
{
unsignedshortfamily;
unsignedshortzero1;
structin_addrip;·
unsignedintzero2;
unsignedintzero3;·
unsignedintmetric;
};
structrip_packet
{
unsignedcharcommand;
unsignedcharversion;
unsignedshortzero;
structrip_entryrip_entries[RIP_MAX_ENTRY];
};
structroute_entry
{
structin_addrdest;
structin_addrnext;
unsignedintmetric;
time_ttimer;
intvalid;
intflag;
};
structrip_packetcurrent_rip_packet;
//structrip_packetcurrent_rip_packet_r;
intcurrent_rip_count;
structroute_entryrouting_table[ROUTE_MAX_ENTRY];
intcurrent_route_count;
intsockfd;
pthread_mutex_trt_mutex;
pthread_mutex_tcrp_mutex;
structin_addrlocal_addr;
voidprint_routing_table();
voidprint_message();
voidprint_rip_packet();
intcheck_rip_packet();
intcalculate_rip_metric(intrip_entry_number);
voidreset_rip_packet(intcommand);
voidinit_routing_table();
voidinit_all();
voidgen_request_all();
voidsend_rip_packet_to(structin_addrdest_ip);
voidbroadcast_rip_packet();
voidreceive_rip_packet();
voidhandle_request(structin_addrsource_ip);
voidhandle_response(structin_addrsource_ip);
voidstart_rip_daemon();
voidupdate_routing_table();
void*timer_routine();
char*local_ip[LOCAL_ROUTE_ENTRY]={
"195.51.0.0",
"195.51.0.1",
"195.51.0.2",
"195.51.0.3",
"195.51.0.4",
"195.51.0.5",
"195.51.0.6",
"195.51.0.7",
"195.51.0.8",
"195.51.0.9"
};
#endif
RIP.c
#include"myrip.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
voidrp_inverse_ntoh()
{
void*tempptr=¤t_rip_mand;
unsignedshort*temp=(unsignedshort*)(tempptr);
*temp=ntohs(*temp);
for(inti=0;i { current_rip_packet.rip_entries[i].metric=ntohl(current_rip_packet.rip_entries[i].metric); } } voidrp_inverse_hton() { void*tempptr=¤t_rip_mand; unsignedshort*temp=(unsignedshort*)(tempptr); //unsignedshort*temp=(unsignedshort*)(¤t_rip_packet); *temp=htons(*temp); //current_rip_packet.version=htons(current_rip_packet.version); for(inti=0;i { current_rip_packet.rip_entries[i].metric=htonl(current_rip_packet.rip_entries[i].metric); } } voidprint_routing_table() { charbuf[INET_ADDRSTRLEN]; size_tbuf_len=sizeof(buf); constchar*buf_ptr; printf("currentroutingtable----\n"); for(inti=0;i { printf("%dthre: \n",i); buf_ptr=inet_ntop(AF_INET,&routing_table[i].dest,buf,buf_len); printf("destination: %s",buf); buf_ptr=inet_ntop(AF_INET,&routing_table[i].dest,buf,buf_len); printf("next: %s",buf); printf("metric: %d\n\n",routing_table[i].metric); } printf("\n"); } voidprint_message(constchar*title,constchar*content) { printf("\n%s---\n",title); printf("-%s-\n",content); printf("endofmessage\n"); } voidprint_rip_packet() { printf("rippacketcontains%dentries: -\n",current_rip_count); printf("command: %s",((current_rip_mand==RIP_RESPONSE)? "RESPONSE": "REQUEST")); printf("version: %d\n",current_rip_packet.version); for(inti=0;i { printf("entry%d: ",i); printf("ip: %s",inet_ntoa(current_rip_packet.rip_entries[i].ip));
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- RIP协议设计 毕业课程设计报告包含源代码 RIP 协议 设计 毕业 课程设计 报告 包含 源代码