RIP协议设计毕业课程设计报告(包含源代码).doc_第1页
RIP协议设计毕业课程设计报告(包含源代码).doc_第2页
RIP协议设计毕业课程设计报告(包含源代码).doc_第3页
RIP协议设计毕业课程设计报告(包含源代码).doc_第4页
RIP协议设计毕业课程设计报告(包含源代码).doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

网络程序设计课程设计报告题 目 RIP协议设计 专业及班级 网络工程1101班 学 号 姓 名 日 期 2012年7月3日 一、 课程设计目的了解RIP协议的原理和应用等相关知识,通过距离矢量算法来实现最短传输路径的路由选择。通过本次课程设计,可以对RIP协议的工作原理和实现机制,路由表的建立和路由信息的更新等有更直观和清晰的认识。程序运行后能与路由器的RIP协议程序正确通信。查阅相关RFC。提供配置命令,程序运行后能动态设置协议参数。 收到的数据先放入循环队列,再从队列中取出依次处理。使用定时器处理超时事件。二、 设计与实现2.1 RIP协议的报文格式分析对于RIP报文有两种版本的格式,Version 1和Version 2。两种报文稍有不同,如所示分别为RIPv1和RIPV2:命令版本全零地址族全零 IP地址 全零 全零 度量值 前20个字节的重复命令版本路由选择 地址族路径标签 IP地址 子网掩码 下一个站点的IP地址 度量值 前20个字节的重复RIP报文中至多可以出现25个AFI、互联网络地址和度量域。这样允许使用一个RIP报文来更新一个路由器中的多个路由表项。包含多个路由表项的RIP报文只是简单地重复从AFI到度量域的结构,其中包括所有的零域。图表 2显示了路由信息域中只带一个目的地的RIP报文。1字节命令1字节版本2字节0域2字节AFI2字节0域4字节网络地址4字节0域4字节0域4字节度量图表 1图表 3具有两个表项的RIP报文1字节命令1字节 版本2字节 0域两字节AFI2字节0域4字节网络地址4字节0域4字节0域4字节度量4字节网络地址4字节0域4字节0域4字节度量图表 2地址域可以既包括发送者的地址也包括发送者路由表中的一系列IP地址。请求报文含有一个表项并包括请求者的地址。应答报文可以包括至多2 5个RIP路由表项。 2.2 RIP的工作原理RIP协议是矢量距离算法在局域网上的直接实现,RIP将协议的参加者分为主动机和被动机两种。主动机主动地向外广播路径刷新报文,被动机被动地接受路径刷新报文。一般情况下,网关作主动机,主机作被动机。RIP规定,网关每30秒向外广播一个报文,报文信息来自本地路由表。RIP的度量是基于跳数(hopscount)的,每经过一台路由器,路径的跳数加一。如此一来,跳数越多,路径就越长,RIP算法会优先选择跳数少的路径。RIP支持的最大跳数是15,跳数为16的网络被认为不可达。对于相同开销路径的处理是采用先入为主的原则。在具体的应用中,可能会出现这种情况,去往相同网络有若干条相同距离的路径。在这种情况下,无论哪个网关的路径广播报文先到,就采用谁的路径。直到该路径失败或被新的更短的路径来代替。RIP中路由的更新是通过定时广播实现的。缺省情况下,路由器每隔30秒向与它相连的网络广播自己的路由表,接到广播的路由器将收到的信息添加至自身的路由表中。每个路由器都如此广播,最终网络上所有的路由器都会得知全部的路由信息。正常情况下,每30秒路由器就可以收到一次路由信息确认,如果经过180秒,即6个更新周期,一个路由项都没有得到确认,路由器就认为它已失效了。如果经过240秒,即8个更新周期,路由项仍没有得到确认,它就被从路由表中删除。上面的30秒,180秒和240秒的延时都是由计时器控制的,它们分别是更新计时器(UpdateTimer)、无效计时器(InvalidTimer)和刷新计时器(FlushTimer)。距离向量类的算法容易产生路由循环,RIP是距离向量算法的一种,所以它也不例外。如果网络上有路由循环,信息就会循环传递,永远不能到达目的地。如果出现环路,直到路径长度达到16,也就是说要经过210秒(30X7秒)来回,路径回路才能被解除,这就是所谓的慢收敛问题。是RIP的一个很大的缺陷,为了避免这个问题,RIP等距离矢量算法实现了4个机制: 水平分割(splithorizon)水平分割保证路由器记住每一条路由信息的来源,并且不在收到这条信息的端口上再次发送它。这是保证不产生路由循环的最基本措施。毒性逆转(poisonreverse)当一条路径信息变为无效之后,路由器并不立即将它从路由表中删除,而是用16,即不可达的度量值将它广播出去。这样虽然增加了路由表的大小,但对消除路由循环很有帮助,它可以立即清除相邻路由器之间的任何环路。触发更新(triggerupdate)当路由表发生变化时,更新报文立即广播给相邻的所有路由器,而不是等待30秒的更新周期。同样,当一个路由器刚启动RIP时,它广播请求报文。收到此广播的相邻路由器立即应答一个更新报文,而不必等到下一个更新周期。这样,网络拓扑的变化会最快地在网络上传播开,减少了路由循环产生的可能性。抑制计时(hold downtimer)一条路由信息无效之后,一段时间内这条路由都处于抑制状态,即在一定时间内不再接收关于同一目的地址的路由更新。如果,路由器从一个网段上得知一条路径失效,然后,立即在另一个网段上得知这个路由有效。这个有效的信息往往是不正确的,抑制计时避免了这个问题,而且,当一条链路频繁起停时,抑制计时减少了路由的浮动,增加了网络的稳定性。即便采用了上面的4种方法,路由循环的问题也不能完全解决,只是得到了最大程度的减少。一旦路由循环真的出现,路由项的度量值就会出现计数到无穷大(Count to Infinity)的情况。这是因为路由信息被循环传递,每传过一个路由器,度量值就加1,一直加到16,路径就成为不可达的了。RIP选择16作为不可达的度量值是很巧妙的,它既足够的大,保证了多数网络能够正常运行,又足够小,使得计数到无穷大所花费的时间最短。有些网络是NBMA(Non-Broadcast Multi Access,非广播多路访问)的,即网络上不允许广播传送数据。对于这种网络,RIP就不能依赖广播传递路由表了。解决方法有很多,最简单的是指定邻居(neighbor),即指定将路由表发送给某一台特定的路由器。2.3 主要函数模块说明2.3.1 get_local_ip()该函数主要是通过gethostname()函数获取本地ip,并将其赋值给local_addr;2.3.2 broadcast_rip_packet()首先将包转换成网络读取数据的顺序,然后将要广播的ip和协议封装在一个结构体中,从定义的RIP端口520广播出去。print_rip_packet()-rp_inverse_hton()-socket()-sendto()-close()2.3.3 timer_routine()使用线程的pthread_mutex_lock()和pthread_mutex_unlock()对路由表更新模块进行保护,以防资源被更改。2.3.4 receive_rip_packet()从网络上接受包,并解析结构体过去包的ip,通过520端口获得包,并检查包的格式,然后分析包的命令是请求还是相应给于相应的处理。socket()-bind()-recvfrom()-rp_inverse_ntoh()-print_rip_packet()-check_rip_packet()2.3.5 handle_request()先检查路由表是否为空,为空则返回错误信息,不为空则返回rip包和路由表。2.3.6 handle_response() 返回自身的rip包和路由表。2.4 实现方法2.4.1 包的包装和解析通过定义struct rip_entry、struct rip_packet、struct route_entry三个结构体分别对rip和路由表进行包装,然后解析过程则只需通过获取结构体的成员便可得到相应的部分然后进行相应的处理。2.4.2 加锁和解锁过程应用函数:update_routing_table() 功能:通过加锁和解锁使得在更新路由表过程中路由表中的数据不会被其他的线程更改,例如:打印路由表,处理请求和应答等。2.5 RIP协议的运行过程网关刚启动时,运行VD算法,对VD路由表进行初始化,为每一个和它直接相连的实体建一个表目,并设置目的IP地址,距离为1(这里RIP和VD略有不同),下一站的IP为0,还要为这个表目设置两个定时器(超时计时器和垃圾收集计时器)。每隔30秒就向它相邻的实体广播路由表的内容。相邻的实体收到广播时,在对广播的内容进行细节上的处理之前,对广播的数据报进行检查。因为广播的内容可能引起路由表的更新,所以这种检查是细致的。首先检查报文是否来自端口520的UDP数据报,如果不是,则丢弃。否则看RIP报文的版本号:如果为0,这个报文就被忽略;如果为1,检查必须为0的字段,如果不为0,忽略该报文;如果大于1,RIP1对必须为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 /包含了的C语言标准库函数的定义#include /有关标准输入输出的信息#include /常数和类型都定义#include / 时间类型#include #include / 基本系统数据类型#include #include #include #include /INTERNET地址族#include / INTERNET定义#include #include #include #define RIP_VERSION 1 #define RIP_REQUEST 1#define RIP_RESPONSE 2#define RIP_INFINITY 16#define RIP_MAX_ENTRY 25#define RIP_MAX_PACKET 504#define RIP_PACKET_HEAD4#define RIP_PORT520#define ROUTE_MAX_ENTRY 256#define LOCAL_ROUTE_ENTRY 10#define ROUTE_VALID1#define ROUTE_UNVALID0#define RIP_CHECK_OK1#define RIP_CHECK_FAIL0#define BROADCAST_INTERVAL10#define CLOCK_TIMEOUT15#define GARBAGE_REMOVE_TIMEOUT 25struct rip_entry/RIP unsigned short family; unsigned short zero1; struct in_addr ip; unsigned int zero2; unsigned int zero3; unsigned int metric;struct rip_packet unsigned char command; unsigned char version; unsigned short zero; struct rip_entry rip_entriesRIP_MAX_ENTRY;struct route_entry struct in_addr dest; struct in_addr next; unsigned int metric; time_t timer; int valid; int flag;struct rip_packet current_rip_packet;/struct rip_packet current_rip_packet_r;intcurrent_rip_count;struct route_entryrouting_tableROUTE_MAX_ENTRY;intcurrent_route_count;intsockfd;pthread_mutex_t rt_mutex;pthread_mutex_t crp_mutex;struct in_addr local_addr;void print_routing_table();void print_message();void print_rip_packet();int check_rip_packet();int calculate_rip_metric(int rip_entry_number);void reset_rip_packet(int command);void init_routing_table();void init_all();void gen_request_all();void send_rip_packet_to(struct in_addr dest_ip);void broadcast_rip_packet();void receive_rip_packet();void handle_request(struct in_addr source_ip);void handle_response(struct in_addr source_ip);void start_rip_daemon();void update_routing_table();void * timer_routine();char * local_ipLOCAL_ROUTE_ENTRY= , , , , , , , , , ;#endifRIP.c#include myrip.h#include #include #include #include #include #include #include #include #include #include #include #include #include #include void rp_inverse_ntoh() void * tempptr = & current_rip_mand; unsigned short * temp = (unsigned short *)( tempptr ); *temp = ntohs(* temp); for(int i=0; i current_rip_count; i+) current_rip_packet.rip_entriesi.metric = ntohl(current_rip_packet.rip_entriesi.metric); void rp_inverse_hton() void * tempptr = & current_rip_mand; unsigned short * temp = (unsigned short *)( tempptr ); /unsigned short * temp = (unsigned short *)( & current_rip_packet); *temp = htons(* temp); /current_rip_packet.version = htons(current_rip_packet.version); for(int i=0; i current_rip_count; i+) current_rip_packet.rip_entriesi.metric = htonl(current_rip_packet.rip_entriesi.metric); void print_routing_table() char bufINET_ADDRSTRLEN; size_tbuf_len = sizeof(buf); const char*buf_ptr; printf(current routing table-n); for (int i = 0; i current_route_count; i+) printf(%dth re:n, i); buf_ptr = inet_ntop(AF_INET, &routing_tablei.dest, buf, buf_len); printf(destination: %s , buf); buf_ptr = inet_ntop(AF_INET, &routing_tablei.dest, buf, buf_len); printf(next: %s , buf); printf(metric: %dnn, routing_tablei.metric); printf(n);void print_message(const char* title, const char* content) printf(n %s -n, title); printf(- %s -n, content); printf(end of message n);void print_rip_packet() printf(rip packet contains %d entries: -n, current_rip_count); printf(command: %s ,(current_rip_mand = RIP_RESPONSE)?RESPONSE:REQUEST); printf(version: %dn,current_rip_packet.version); for(int i = 0; i current_rip_count; i+) printf(entry %d: ,i); printf(ip: %s ,inet_ntoa(current_rip_packet.rip_entriesi.ip); printf(metric: %dn,current_rip_packet.rip_entriesi.metric); printf(n);int check_rip_packet() if (current_rip_packet.version = 2)return RIP_CHECK_OK; if (current_rip_packet.version = 0)return RIP_CHECK_FAIL; /check mbz if (current_rip_packet.zero)return RIP_CHECK_FAIL; for (int i = 0; i RIP_INFINITY) return RIP_INFINITY; return current_rip_packet.rip_entriesrip_entry_number.metric + 1;void reset_rip_packet(int command) current_rip_count = 0; current_rip_mand = command; current_rip_packet.version = 1; current_rip_packet.zero = 0; for (int i = 0; i RIP_MAX_ENTRY; i+) current_rip_packet.rip_entries0.family = 2;current_rip_packet.rip_entries0.zero1 = 0;current_rip_packet.rip_entries0.ip.s_addr = 0;current_rip_packet.rip_entries0.zero2 = 0;current_rip_packet.rip_entries0.zero3 = 0;current_rip_packet.rip_entries0.metric = 0; void reset_routing_table() current_route_count = 0; for (int i = 0; i ROUTE_MAX_ENTRY; i+) routing_tablei.dest.s_addr = 0;routing_tablei.next.s_addr = 0;routing_tablei.metric = 0;routing_tablei.valid = 1;routing_tablei.timer = 0;routing_tablei.flag = 0; void init_routing_table() reset_routing_table(); for (int i = 0; i LOCAL_ROUTE_ENTRY; i+) if (inet_pton(AF_INET, local_ipi, &(routing_tablei.dest) = 0) printf(inet_pton errorn); if (inet_pton(AF_INET, local_ipi, &(routing_tablei.next) = 0) printf(inet_pton errorn);routing_tablei.metric = 1;routing_tablei.timer = time(NULL);routing_tablei.valid = ROUTE_VALID;routing_tablei.flag = 0; current_route_count = LOCAL_ROUTE_ENTRY;void get_local_ip() char ac80; if (gethostname(ac, sizeof(ac) = -1) / cerr Error WSAGetLastError() / when getting local host name. endl; return ; printf(Host name is %s, , ac); struct hostent *phe = gethostbyname(ac); if (phe = 0) /cerr Yow! Bad host lookup. h_addr_listi != 0; +i) local_addr; memcpy(&local_addr, phe-h_addr_listi, sizeof(struct in_addr); printf(Address %d: %s n=n,i, inet_ntoa(local_addr); void init_all() get_local_ip(); reset_rip_packet(RIP_RESPONSE); init_routing_table();void gen_request_all() current_rip_count = 1; current_rip_mand = RIP_REQUEST; current_rip_packet.version = 1; current_rip_packet.zero = 0; current_rip_packet.rip_entries0.family = 0; current_rip_packet.rip_entries0.zero1 = 0; current_rip_packet.rip_entries0.ip.s_addr = 0; current_rip_packet.rip_entries0.zero2 = 0; current_rip_packet.rip_entries0.zero3 = 0; current_rip_packet.rip_entries0.metric = RIP_INFINITY;void send_rip_packet_to(struct in_addr dest_ip) printf(begin sending rip packet:n); print_rip_packet(); rp_inverse_hton(); struct sockaddr_in addr; int addr_len = sizeof(struct sockaddr_in); bzero(&addr, addr_len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(dest_ip.s_addr); /addr.sin_port = htons(RIP_PORT); addr.sin_port = htons(RIP_PORT); int sockfd = socket(AF_INET, SOCK_DGRAM, 0); int val = 1; /*/*/bind(sockfd, (struct sockaddr*)&addr, sizeof(addr); setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val); / reverseMessage(); if (sendto(sockfd, ¤t_rip_packet, RIP_PACKET_HEAD+ current_rip_count*sizeof(struct rip_entry) , 0,(const struct sockaddr*)&addr, addr_len) 0) printf(sent green in send_rip_packet_ton); close(sockfd);return;void broadcast_rip_packet() printf(begin broadcasting rip packet:n); print_rip_packet(); rp_inverse_hton(); struct sockaddr_in addr; int addr_len = sizeof(struct sockaddr_in); bzero(&addr, addr_len); addr.sin_family = AF_INET; /inet_aton(70, &addr.sin_addr); addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); /addr.sin_addr.s_addr=htonl(addr.sin_addr.s_addr); addr.sin_port = htons(520); /printf(sending rip packet.n); int sockfd = socket(AF_INET, SOCK_DGRAM, 0); int val = 1; /bind(sockfd, (struct sockaddr*)&addr, sizeof(addr); setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val); if (sendto(sockfd, ¤t_rip_packet, RIP_PACKET_HEAD+current_rip_count*sizeof(struct rip_entry), /sizeof(current_rip_packet), 0, (struct sockaddr*)&addr, addr_len) 0) printf(broadcast error in broadcast_rip_packetn); close(sockfd); return;void receive_rip_packet() struct sockaddr_in addr; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd 0) printf(open socket error in start_rip_daemonn);exit(-1); bzero(&addr, sizeof(struct sockaddr_in); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(RIP_PORT); /*if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in) 0) printf(bind error in start_ripn); exit(-1); */ /struct sockaddr_in addr; int addr_len = sizeof(struct sockaddr_in); int packet_len = 0; packet_len = recvfrom(sockfd, ¤t_rip_packet, RIP_PACKET_HEAD + RIP_MAX_PACKET, 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len); if (packet_len 0) printf(rip packet bad!n);return; current_rip_count = (packet_len - RIP_PACKET_HEAD) / sizeof(struct rip_entry); /-inverse rp_inverse_ntoh(); /-end inverse struct in_addr source_addr; source_addr.s_addr = addr.sin_addr.s_addr; /char * temptemp=000.000.000.000; /inet_ntop(AF_INET, &source_addr.s_addr, temptemp, sizeof(temptemp); /printf(%sn,inet_ntoa(source_addr); if(source_addr.s_addr != local_addr.s_addr) printf(packet received from %sn, inet_ntoa(source_addr);print_rip_packet();if (check_rip_packet() = RIP_CHECK_OK) pthread_mutex_lock(&rt_mutex); switch(current_rip_mand) case RIP_REQUEST:handle_request(source_addr);break; case RIP_RESPONSE:handle_response(source_addr);break; default:break; pthread_mutex_unlock(&rt_mutex); else print_message(error:, packet check error); void handle_request(struct in_addr source_ip) if (current_route_count = 0) print_message(warnning:, the route table is empty);return; / reset_rip_packet(RIP_RESPONSE); /request for the whole route_table if (current_rip_count = 1 & current_rip_packet.rip_entries0.family = 0 & current_rip_packet.rip_entries0.metric = 16) int rou

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论