网络模拟和协议仿真课程设计报告.docx
- 文档编号:9679722
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:45
- 大小:169.27KB
网络模拟和协议仿真课程设计报告.docx
《网络模拟和协议仿真课程设计报告.docx》由会员分享,可在线阅读,更多相关《网络模拟和协议仿真课程设计报告.docx(45页珍藏版)》请在冰豆网上搜索。
网络模拟和协议仿真课程设计报告
杭州电子科技大学
网络模拟和协议仿真课程设计
课程题目:
基于NS-2的SDRAD路由协议的实现人员:
*****
2012/9/16
摘要
在网络路由技术的研究中,实际网络系统的实现往往是代价很高或不现实的。
利用网络仿真器NS2对相关网络路由协议进行仿真是一种既有效又经济的研究方法,但目前的NS2还不能支持所有网络路由协议的仿真。
本文根据拓展仿真的原理和方法,对在NS2中添加路由协议进行了研究,添加了SDRAD路由协议。
关键词:
NS2;拓展仿真;路由协议;SDRAD
引言
在真实的网络中,设计和调试网络协议是一件困难且复杂的事情,仿真成了最佳可供选择的测试、评估和验证手段之一。
网络仿真是用计算机程序对通信网络进行模型化,通过程序的运行模仿通信网络的运行过程。
这是一种进行网络技术研究的基本手段,不仅适用于网络模型的构造和设计、协议性能的评价与分析,还适用于网络协议的开发与研究以及真实网络的故障诊断。
网络模拟器NS2(NetworkSimulatorv2)是一种免费、源代码公开的模拟软件平台,其协议代码与真实网络应用代码很相似,仿真结果具有可靠性。
NS2是一个面向对象的离散事件驱动网络模拟器,支持多种流行的网络协议如TCP、UDP和路由调度、拥塞控制算法等。
相对于一般的离散型模拟器,NS2的优势在于它有非常丰富的构件库,而且这些对象易于组合,易于拓展,但是对用户的编程能力,实际网络协议的理解能力要求较高。
本文利用NS2已有的对象,组合所要研究的网络系统模型,在NS2中添加了一个SDRAD[1]路由协议进行网络仿真。
由于无线传感器网络的众多优势,如可迅速大规模部署、可进行各种环境下的长期监测、可减少人为干涉等,使得它逐步应用到各种军事和民用领域,包括环境监测、智能交通等。
数据收集是无线传感器网络路由中的一种特殊情况,主要任务是通过单跳或多跳的方式将网络中传感器节点收集的数据传送给基站。
在环境监测应用中。
可采用数据收集的方式将数据汇集到汇聚节点.再进行进一步分析。
用无线传感器网络进行环境数据收集时。
不同于其他对实时性要求比较高的应用,其对数据传输的延迟性没有太大要求,数据传输速率也较低,对带宽也无过高要求。
如何降低网络能耗、延长网络生命周期成了环境监测中数据收集的首要问题。
DRAD[2]路由协议可以很好地满足上面提到的要求。
为了模拟DRAD的原理,对它进行了简化,形成了SDRAD协议。
第一章协议介绍
先来介绍一下DRAD协议,DRAD是(aDatacollectionRoutingalgorithmbasedonAsynchronousDuty-cycleinWirelessSensorNetworks)的简称,是一种基于异步休眠调度、用于环境监监测应用的数据收集协议。
节点定期收集环境信息汇总到基站。
为了将数据传送到基站,DRAD将网络描述成树状结构。
节点将自身感知到的数据或者需要转发的数据通过下一跳节点向基站方向发送。
但是,节点不是仅仅维护其下一跳节点的信息,而是维护所有邻居的信息。
当节点的下一跳节点失效时可以采用迂回策略,使数据包最终到达基站。
网络中的节点按照一定的规律进行休眠调度,节点维护的邻居相关信息除了最小跳步数、剩余能量、链路质量等常用选路困素外,还包括计算其醒来的时间差。
网络不需要全局或局部的时间同步,也不要求节点修改内部时钟。
而是通过记录的与邻居节点的时间差,决定发送数据包的时刻。
此外,可以通过发送的数据包和接收节点回馈的ACK进行时间差修补。
对下一跳节点进行选择时,加入对邻居节点醒来先后顺序的考虑。
为了简单起见,路由方面借鉴经典的基于地理位置路由的选路策略,如贪婪路由、对网络空洞的处理。
休眠调度也是利用简单的调度策略,实现定义节点的睡眠和活跃周期。
SDRAD路由协议是对DRAD协议的简写,简化了的DRAD协议。
SDRAD主要实现了建立网络结构,收集数据信息的功能[3]。
第二章协议设计
SDRAD协议分两个阶段:
网络拓扑形成阶段和数据收集阶段。
接下来将对
这两个阶段进行详细说明。
2.1网络拓扑形成阶段
当节点部署到网络并开启电源后,并不是立即进入数据收集。
而是首先由基站发送Hello包,节点接受到Hello包后,更新自己的邻居节点信息,从而建立树状的网络结构。
协议刚启时,所有节点的跳步数都为无穷大。
首先,由基站广播Hello包,为了简单,本例中将基站固定为序列号为0的节点。
节点接收到Hello包后,更新本节点跳步数和邻居列表,广播自身。
Hello包的分组头
包类型
(Packettype)
跳步数(Hopcount)
源节点序列号
(Sourcenodesequence)
节点的分布及形成的拓扑关系:
图1结点分布
如图1,网络中共有0~7个节点,其中节点0为基站,其跳步数为0。
节点1,2的跳步数为1,节点3,4,5的跳步数为2,节点6的跳步数为3。
在网络形成阶段由基站发送Hello包,节点1,2接收到Hello包,将节点0加入到它们的邻居表中,同时节点1,2重新向外发送Hello包,被节点3,4,5接收,依次建立邻居表,形成SDRAD的拓扑关系。
结点
结点0
结点1
结点2
结点3
结点4
结点5
结点6
0
0
1
2
1
2
1
2
3
4
5
2.2数据收集阶段
进入数据收集阶段后,当网络中某一节点接受到数据包后,该节点就会向邻居表中的某一节点发送数据收集包(collect包),最终将接收到的数据信息发送到基站,传给应用程序进行处理。
选择哪一个邻居节点呢?
协议将随机选择邻居表的一个节点进行转发。
图2数据转发路径图
如图2,节点6接收到数据信息,节点6将该数据封装成Collect包,依次传送给节点5、节点1、在到基站(节点0)。
路径中结点5与结点1都是随机选择的。
第三章协议实现
3.1SDRAD协议类
为了实现SDRAD协议类,我们编写了4个程序文件,分别是sdrad.h、sdrad.cc(SDRAD协议的定义和实现)、sdrad_packet.h(SDRAD新增包头的定义)、sdrad_nbtable.h(邻居表的定义和实现)。
在ns2中,所有路由协议都是从Agent类继承而来的,实现协议时主要关心的是节点对包的接收和发送,即recv函数和send函数。
Recv函数一般从Agent类继承而来,send函数根据需要自己编写。
下面给出SDRAD协议类的定义:
classSDRAD:
publicAgent{
friendclassSDRAD_Neighbor;//SDRAD_Neighbor类是邻居表类
friendclassSDRAD_HelloTimer;//Hello定时器类
public:
SDRAD(nsaddr_tid);//含一个参数的构造函数
voidrecv(Packet*p,Handler*);//接收上层协议送下来的数据并处理
protected:
//命令处理函数,实现Tcl和C++之间的信息交换
intcommand(int,constchar*const*);
inlineintinitialized(){return1&&target_;}
//对上层发送的数据进行处理
voidresolve(Packet*p);
//邻居表的信息维护
voidnb_insert(u_int32_tseqno,u_int8_thop);//插入
SDRAD_Neighbor*nb_lookup(u_int32_tseqno);//查找
voidnb_delete(u_int32_tseqno);//删除
voidnb_purge();//清空
voidnb_print();//打印,检验协议所建立的拓扑是否符合要求
voidforward(u_int32_tseqno,Packet*p,doubledelay);//转发函数
voidsendHello(boolisbase);//发送Hello包
//PacketRXRoutines
voidrecvHello(Packet*p);//接收Hello包
//接收SDRAD包(包括Hello包和Collect包)
voidrecvSDRAD(Packet*p);
//PacketcollectRoutines,发送、接收Collect包
voidsendCollect(u_int32_tipdst);
voidrecvCollect(Packet*p);
//Timers
SDRAD_HelloTimerhtimer;//定义定时器
private:
//本协议中为了简化处理,将IP地址和序列号设置为同一唯一值
nsaddr_tindex_;//本节点的IP地址
u_int32_tseqno_;//本节点的序列号
u_int8_thop_count_;//节点跳步数
protected:
SDRAD_nbtablenbthead_;//定义邻居表
//为调试和跟踪定义的变量
Trace*logtarget_;
NsObject*uptarget_;
NsObject*port_dmux_;
};
其构造函数的实现:
voidSDRAD:
:
SDRAD(nsaddr_tid):
Agent(PT_SDRAD),port_dmux_(0),htimer(this){
index_=id;
seqno_=id;//
hop_count_=INFINITY;//跳步数为无穷大
logtarget_=0;
LIST_INIT(&nbthead_);
length=0;//邻居表长度
}
3.2数据包头
现在,我们为SDRAD协议新建包头,对应实现协议中的分组头。
下述代码在sdrad_packet.h中:
//SDRAD包头:
hdr_sdrad
structhdr_sdrad{
u_int8_tdh_type;//分组类型
staticintoffset_;
inlinestaticint&offset(){returnoffset_;}
inlinestatichdr_sdrad*access(constPacket*p){
return(hdr_sdrad*)p->access(offset_);
}
};
Hello包头:
hdr_sdrad_hello
structhdr_sdrad_hello{
u_int8_thh_type;//分组类型
u_int8_thh_hop_count;//跳步数
u_int32_thh_src_seq;//源节点序列号
//计算包头大小
inlineintsize(){
intsz=0;
sz=sizeof(u_int8_t)
+sizeof(u_int8_t)
+sizeof(u_int32_t);
returnsz;
}
};
Collect包头:
hdr_sdrad_collect
structhdr_sdrad_collect{
u_int8_thc_type;//分组类型
u_int8_thc_hop_count;//跳步数
u_int32_thc_src_seq;//源节点序列号
u_int32_thc_dst_seq;//目的节点序列号
inlineintsize(){//计算包头大小
intsz=0;
sz=sizeof(u_int8_t)
+sizeof(u_int8_t)
+sizeof(u_int32_t)
+sizeof(u_int32_t);
returnsz;
}
};
//联合SDRAD的分组头,节约空间便于使用
unionhdr_all_sdrad{
hdr_sdraddh;
hdr_sdrad_hellohh;
hdr_sdrad_collecthc;
};
3.3邻居表
在ns2中内置了一个链表结构list(源码在~ns/lib/bsd-list.h中),在此使用这个list结构实现邻居类(sdrad_nbtable.h):
#include
classSDRAD_Neighbor{
friendclassSDRAD;//设置SDRAD为友元
public:
SDRAD_Neighbor(u_int32_ts,u_int8_thop){//构造函数
seqno_=s;
hop_count_=hop;
}
protected:
//链表结构
LIST_ENTRY(SDRAD_Neighbor)nb_link;
//邻居结点中的字段
u_int32_tseqno_;//序列号
u_int8_thop_count_;//跳步数
};
//定义链表结构
LIST_HEAD(SDRAD_nbtable,SDRAD_Neighbor);
解释类的定义和编译类的联接
解释类和编译类的连接方法比较固定,对于只关心协议内容的人,可参考ns2中同层协议的实现方法。
TclHooks
到目前为止,我们的SDRAD协议还不能被ns所认可,还需要其它定义。
下面部分是不可缺少的,而且通常只需要按照这个典型模式实现。
其中Agent\SDRAD指定了C++中的SDRAD类和Tcl部分中的Agent/SDRAD绑定在了一起。
//sdrad.cc文件中:
//TCLHooks
staticclassSDRADclass:
publicTclClass{
public:
SDRADclass():
TclClass("Agent/SDRAD"){}
TclObject*create(intargc,constchar*const*argv){
assert(argc==5);
return(newSDRAD((u_int32_t)atoi(argv[4])));
}
}class_rtProtoSDRAD;
3.4SDRAD协议类的实现
3.4.1邻居表管理
本部分功能实现对邻居表的增删查改等,方便代理类的使用。
1>插入
新建一个邻居节点,插入nbtable中。
voidSDRAD:
:
nb_insert(u_int32_tseqno,u_int8_thop)
2>查找
查找序列号为seqno的节点
SDRAD_Neighbor*SDRAD:
:
nb_lookup(u_int32_tseqno)
3>删除
删除序列号为seqno的节点
voidSDRAD:
:
nb_delete(u_int32_tseqno)
4>清空
清空邻居表
voidSDRAD:
:
nb_purge()
5>打印
输出邻居表的跳步数和序列号
voidSDRAD:
:
nb_print()
3.4.2SDRAD路由协议中的关键函数
1>command函数
intSDRAD:
:
command(intargc,constchar*const*argv)
command函数的写法固定,主要实现Otcl和C++的交互,对Otcl命令
进行解析。
用来解析模拟器类create-sdrad-agent函数中的命令。
Simulatorinstproccreate-sdrad-agent{node}{
#CreateSDRADroutingagent
setragent[newAgent/SDRAD[$nodeid]]
puts"=======[$nodeid]========";#测试
$selfat0.0"$ragentstart";#在0.0s启动协议
$nodesetragent_$ragent
return$ragent
}
2>recv函数
voidSDRAD:
:
recv(Packet*p,Handler*)
新协议类重载recv函数,判别分组包类型,并对其进行转发、更新、丢弃、重发等处理,来实现具体协议所要求的内容。
3>sendHello函数
voidSDRAD:
:
sendHello(boolisbase){
发送hello数据包。
基站只处理发送一次Hello包,非基站节点根据自身信息新建Hello包,广播。
4>recvHello函数
voidSDRAD:
:
recvHello(Packet*p)
基站接收到Hello包,丢弃;节点接收到自身广播的Hello包,丢弃;节点接收到有效Hello包,更新本节点的跳步数,将上一跳节点信息加入邻居表,并广播自身;丢弃重复邻居Hello包和非邻居包。
5>HelloTimer定时器
运行一段时间的网络会不稳定(包括网络中有新结点加入,节点寿命结束,能量用尽等),用HelloTimer定时器定时发送Hello包,更新邻居信息,建立新的树状网络结构。
sdrad.h中HelloTimer的定义:
classSDRAD_HelloTimer:
publicHandler{
public:
SDRAD_HelloTimer(SDRAD*a):
agent(a){}
voidhandle(Event*);
private:
SDRAD*agent;
Eventintr;
};
重写handle函数,使基站发送Hello包,建立新的网络结构:
voidSDRAD_HelloTimer:
:
handle(Event*){
agent->nb_purge();//清楚邻居表
agent->sendHello(true);//基站发送Hello包
//该定时器每个50s调度一次
Scheduler:
:
instance().schedule(this,&intr,50);
}
6>Resolve函数
voidSDRAD:
resolve(Packet*p)
节点通过第一节点建立好网络结构后,就进入数据收集阶段,此协议通过将有用数据处理成Collect包在网络之间传送。
在recv函数中节点在接收到有用数据后,通过resolve函数将其处理成collect包后转发给邻居节点。
7>下一跳函数
u_int32_tSDRAD:
:
nexthop_random()
随机选择邻居表中节点编号
8>转发函数forward
voidSDRAD:
:
forward(u_int32_tseqno,Packet*p,doubledelay)
9>发送collect包函数
voidSDRAD:
:
sendCollect(u_int32_tipdst)
节点根据参数ipdst确定下一跳目的地,发送collect包。
10>接收collect包函数
voidSDRAD:
:
recvCollect(Packet*p)
节点随机选择下一跳,发送collect包。
基站处理数据,丢弃废包。
3.5将SDRAD整合到NS-2.35中
3.5.1建立协议文件
本协议程序共五个文件,分别是:
sdrad_packet.h、sdrad_nbtable.h、sdrad.h和sdrad.cc。
在
3.5.2修改NS-2.35源码
需要改五个文件:
ns-2.35/common/packet.h
ns-2.35/tcl/lib/ns-lib.tcl
ns-2.35/tcl/lib/ns-packet.tcl
ns-2.35/Makefile
1>ns-2.35/common/packet.h文件中找到如下位置,添加红色标记的一行。
staticconstpacket_tPT_PROTONAME=73;
//insertnewpackettypeshere
staticpacket_tPT_NTYPE=75;//ThisMUSTbetheLASTone
找到如下位置,添加红色标记的一行。
name_[PT_DCCP_RESET]="DCCP_Reset";
name_[PT_PROTONAME]="protoname";
name_[PT_SDRAD]="SDRAD";
name_[PT_NTYPE]="undefined";
2>在ns-2.35/tcl/lib/ns-lib.tcl文件中找到如下位置,添加红色标记的一段代码。
AODV{
setragent[$selfcreate-aodv-agent$node]
}
SDRAD{
setragent[$selfcreate-sdrad-agent$node]
}
AOMDV{
setragent[$selfcreate-aomdv-agent$node]
}
在合适的位置加入如下代码:
Simulatorinstproccreate-sdrad-agent{node}{
#CreateSDRADroutingagent
setragent[newAgent/SDRAD[$nodeid]]
puts"=======[$nodeid]========";#测试
$selfat0.0"$ragentstart";#在0.0s启动协议
$nodesetragent_$ragent
return$ragent
}
3>在ns-2.35/tcl/lib/ns-packet.tcl文件中找到如下位置,添加红色标记部分。
MDART#routingprotocolforad-hocnetworks
#AOMDVpatch
AOMDV
Protoname
SDRAD#
4>在ns-2.35/Makefile文件中找到如下位置,添加红色标记部分
wpan/p802_15_4trace.owpan/p802_15_4transac.o\
apps/pbc.o\
protoname/protoname.oprotoname/protoname_rtable.o\
sdrad/sdrad.o\
$(OBJ_STL)
3.5.3编译NS-2.35源文件
在cygwin中运行如下命令完成源文件的编译。
huger@huger-PC~/ns-allinone-2.35
$cdn
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 模拟 协议 仿真 课程设计 报告