以IEEE 802.15.4 仿真实验为例,代码注释仅供参考。
#仿真模块参数设置
set val(chan) Channel/WirelessChannel # 设置信道为无线信道
set val(prop) Propagation/TwoRayGround # 设置无线参数模型为两径模型l
set val(netif) Phy/WirelessPhy/802_15_4 #网络接口模型
set val(mac) Mac/802_15_4 #MAC层类型
set val(ifq) Queue/DropTail/PriQueue ;#接口队列模型。使用被动管理算法
#DropTail,当系统没有空闲缓冲资源时丢弃到达的分组。PriQueue类是优先级队列,优先
#处理路由协议分组。对队列中的分组进行过滤,删除那些具有特定目标地址的分组。
set val(ll) LL #逻辑链路子层 模拟数据链路协议。设置MAC包头部的目的地址
set val(ant) Antenna/OmniAntenna # 天线模型
set val(ifqlen) 150 # 网络接口队列的大小
set val(nn) 7 #移动节点数
set val(rp) AODV # 设定无线路由协议为距离向量路由协议
set val(x) 50 #拓扑范围的宽
set val(y) 50 #拓扑范围的高
set val(nam) WPAN_MAC.nam #用nam指定WPAN_MAC.nam
set val(traffic) ftp # 设置流量协议的类型
set appTime1 7.0 # 仿真时间1
set appTime2 7.1 # 仿真时间2
set appTime3 7.2 # 仿真时间3
set appTime4 7.3 # 仿真时间4
set appTime5 7.4 # 仿真时间5
set appTime6 7.5 # 仿真时间6
set stopTime 100 # 定义停止时间
Phy/WirelessPhy set CSThresh_ 8.54570e-07 #CSThresh载波监听的门槛距离
Phy/WirelessPhy set RXThresh_ 8.54570e-07 #RXThresh成功接收数据包的门槛
Mac/802_15_4 wpanCmd verbose on #开启wpanCmd verbose
Mac/802_15_4 wpanNam namStatus on #将nam状态设置为开启(默认是关闭的)
proc getCmdArgu {argc argv} { #使用 getCmdArgu设置参数
global val #调用全局变量val
for {set i 0} {$i < $argc} {incr i} {
set arg [lindex $argv $i] #利用索引建立数组
if {[string range $arg 0 0] != "-"} continue #判断数组中是否有”-”
set name [string range $arg 1 end] #设置键
set val($name) [lindex $argv [expr $i+1]] #设置值
}
}
getCmdArgu $argc $argv #调用 getCmdArgu函数
#初始化全局变量
set ns [new Simulator] #创建Simulator对象,模拟过程的事件调度
set tracefd [open WPAN_MAC.tr w] #创建并以只写的方式打开tr文件
#记录nam的trace数据
$ns trace-all $tracefd #调用tcl函数trace-all将创建的文件的操作句柄传递给tcl变量
if { "$val(nam)" == "WPAN_MAC.nam" } {
set namtrace [open ./$val(nam) w] #创建并以只写的方式打开nam文件
$ns namtrace-all-wireless $namtrace $val(x) $val(y) #在50m x 50m 拓扑范围内 #建立无线nam追踪
}
$ns puts-nam-traceall {# nam4wpan #} #打印nam追踪信息
set topo [new Topography] #建立一个拓扑对象,以记录移动节点在拓扑内移动的情况
$topo load_flatgrid $val(x) $val(y) #拓扑的范围是x×y(50m x 50m)
set god_ [create-god $val(nn)] #建立一个god对象来对路由协议做性能评价,创建了 #nn个移动节点,nn值为7
set chan_1_ [new $val(chan)] #创建无线信道对象
#配置节点
$ns node-config -adhocRouting $val(rp) \ #设置无线节点参数
-llType $val(ll) \ #设置移动节点的链路层
-macType $val(mac) \ #设置移动节点的MAC层
-ifqType $val(ifq) \ #设置移动节点的队列类型
-ifqLen $val(ifqlen) \ #设置移动节点的队列长度
-antType $val(ant) \ #设置移动节点的天线类型
-propType $val(prop) \ #设置移动节点的无线信号传输模型
-phyType $val(netif) \ #设置移动节点的物理层
-topoInstance $topo \ #设置移动节点的拓扑对象
-agentTrace OFF \ #设置是否打开应用层的trace
-routerTrace OFF \ #设置是否打开路由的trace
-macTrace ON \ #设置是否打开MAC层的trace
-movementTrace OFF \ #设置是否打开移动节点位置和移动信息的trace
-channel $chan_1_ #设置移动节点的无线通信类型
for {set i 0} {$i < $val(nn) } {incr i} { #创建节点
set node_($i) [$ns node] #创建节点
$node_($i) random-motion 0 #取消随机移动
}
#设置移动节点的初始位置
$node_(0) set X_ 25 #节点0 在横向25m处
$node_(0) set Y_ 25 #节点0在纵向25m处
$node_(0) set Z_ 0 #节点0的高度为0
$node_(1) set X_ 20 #节点1在横向20m处
$node_(1) set Y_ 16.34 #节点1在纵向16.34m处
$node_(2) set X_ 15 #节点2在横向15m处
$node_(2) set Y_ 25 #节点2在纵向25m处
$node_(2) set Z_ 0 #节点2的高度为0
$node_(3) set X_ 20 #节点3在横向20m处
$node_(3) set Y_ 33.66 #节点3在纵向33.66m处
$node_(3) set Z_ 0 #节点3的高度为0
$node_(4) set X_ 30 #节点4在横向30m处
$node_(4) set Y_ 33.66 #节点4在纵向33.66m处
$node_(4) set Z_ 0 #节点4的高度为0
$node_(5) set X_ 35 #节点5在横向35m处
$node_(5) set Y_ 25 #节点5在纵向25m处
$node_(5) set Z_ 0 #节点5的高度为0
$node_(6) set X_ 30 #节点6在横向30m处
$node_(6) set Y_ 16.34 #节点6在纵向16.34m处
$node_(6) set Z_ 0 #节点6的高度为0
$ns at 0.0 "$node_(0) NodeLabel PAN Coor" #节点0设置标签
$ns at 0.0 "$node_(0) sscs startPANCoord" #启动个域网坐标
$ns at 0.5 "$node_(1) sscs startDevice 1 0" #0.5秒时启动节点1
$ns at 1.5 "$node_(2) sscs startDevice 1 0" #1.5秒时启动节点2
$ns at 2.5 "$node_(3) sscs startDevice 1 0" #2.5秒时启动节点3
$ns at 3.5 "$node_(4) sscs startDevice 1 0" #3.5秒时启动节点4
$ns at 4.5 "$node_(5) sscs startDevice 1 0" #4.5秒时启动节点5
$ns at 5.5 "$node_(6) sscs startDevice 1 0" #5.5秒时启动节点6
for {set i 0} {$i < $val(nn)} {incr i} {
$ns initial_node_pos $node_($i) 4 #定义每个节点显示大小为4
}
for {set i 0} {$i < $val(nn) } {incr i} {
$ns at $stopTime "$node_($i) reset" #100.0s后重置
}
#设置流量
Mac/802_15_4 wpanNam PlaybackRate 3ms #设置仿真播放速度
$ns at $appTime1 "puts \"\nTransmitting data ...\n\"" #打印Transmitting data ...
proc cbrtraffic { src dst interval starttime } {
global ns node_ #调用全部节点
set udp_($src) [new Agent/UDP] #创建UDP Agent 对象发送端
eval $ns attach-agent \$node_($src) \$udp_($src) #将src节点和发送端绑定
set null_($dst) [new Agent/Null] #创建NULL Agent的客户端
eval $ns attach-agent \$node_($dst) \$null_($dst) #将节点dst和null_绑定
set cbr_($src) [new Application/Traffic/CBR] #添加CBR应用,CBR是一个流量发生器
eval \$cbr_($src) set packetSize_ 70 #cbr包的大小为1000
eval \$cbr_($src) set interval_ $interval #设置cbr包的时间间隔
eval \$cbr_($src) set random_ 0 #设置为非广播包
eval \$cbr_($src) attach-agent \$udp_($src) #绑定CBR应用到UDP Agent上
eval $ns connect \$udp_($src) \$null_($dst) #连接节点src和dst
$ns at $starttime "$cbr_($src) start" #src节点的cbr包在starttime 发送
}
proc poissontraffic { src dst interval starttime } { #建立恶意数据流
global ns node_ #全局变量调用
set udp($src) [new Agent/UDP] #创建UDP Agent 对象发送端
eval $ns attach-agent \$node_($src) \$udp($src) #将src节点和发送端绑定
set null($dst) [new Agent/Null] #创建NULL Agent的客户端
eval $ns attach-agent \$node_($dst) \$null($dst) #将节点dst和null_绑定
set expl($src) [new Application/Traffic/Exponential]#添加expl应用
eval \$expl($src) set packetSize_ 70 #设置cbr包的大小
eval \$expl($src) set burst_time_ 0 #设置burst_time
eval \$expl($src) set idle_time_ [expr $interval*1000.0-70.0*8/250]ms #设置空闲时间
eval \$expl($src) set rate_ 250k #设置expl包的发送速率时1Mb/s
eval \$expl($src) attach-agent \$udp($src) #绑定expl到UDP Agent上
eval $ns connect \$udp($src) \$null($dst) #连接节点src和dst
$ns at $starttime "$expl($src) start" #src节点的cbr包在starttime 发送
}
if { ("$val(traffic)" == "cbr") || ("$val(traffic)" == "poisson") } {
puts "\nTraffic: $val(traffic)" #打印Traffic: cbr/Traffic: possion
puts [format "Acknowledgement for data: %s" [Mac/802_15_4 wpanCmd ack4data]]
#打印ack4data信息
$ns at $appTime1 "Mac/802_15_4 wpanNam PlaybackRate 0.5ms" #设置播放速度
$ns at [expr $appTime1 + 0.5] "Mac/802_15_4 wpanNam PlaybackRate 1.5ms"#加快速度
$val(traffic)traffic 0 1 0.6 $appTime1 #调用traffic 函数
$val(traffic)traffic 3 0 0.6 $appTime3 #调用traffic 函数
$val(traffic)traffic 0 5 0.6 $appTime5 #调用traffic 函数
$ns at $appTime1 "$ns trace-annotate \"(at $appTime1) $val(traffic) traffic from node 0 to node 1\"" #在nam中插入注释
$ns at $appTime3 "$ns trace-annotate \"(at $appTime3) $val(traffic) traffic from node 3 to node 0\"" #在nam中插入注释
$ns at $appTime5 "$ns trace-annotate \"(at $appTime5) $val(traffic) traffic from node 0 to node 5\"" #在nam中插入注释
Mac/802_15_4 wpanNam FlowClr -p AODV -c tomato #设置AODV包为tomato色
Mac/802_15_4 wpanNam FlowClr -p ARP -c green #设置ARP包为绿色
Mac/802_15_4 wpanNam FlowClr -p MAC -s 0 -d -1 -c navy#节点0到1的MAC包为navy
if { "$val(traffic)" == "cbr" } {
set pktType cbr #如果traffic为cbr,则正常传输
} else {
set pktType exp #如果traffic为exp,则进行干扰性传输
}
Mac/802_15_4 wpanNam FlowClr -p $pktType -s 0 -d 1 -c blue #节点0到1的cbr或 #exp包为蓝色
Mac/802_15_4 wpanNam FlowClr -p $pktType -s 3 -d 0 -c green4 #节点3到0为绿色
Mac/802_15_4 wpanNam FlowClr -p $pktType -s 0 -d 5 -c cyan4 #节点3到0为青色
}
proc ftptraffic { src dst starttime } {
global ns node_ #调用全部变量ns 、 node_
set tcp($src) [new Agent/TCP] #创建TCP Agent 对象发送端
eval \$tcp($src) set packetSize_ 50 #设置包的大小为50
set sink($dst) [new Agent/TCPSink] #创建TCP Agent 对象接收端
eval $ns attach-agent \$node_($src) \$tcp($src) #发送端与节点src关联
eval $ns attach-agent \$node_($dst) \$sink($dst) #接收端与节点dst关联
eval $ns connect \$tcp($src) \$sink($dst) #链接TCP发送端和接收端
set ftp($src) [new Application/FTP] #添加FTP应用
eval \$ftp($src) attach-agent \$tcp($src) #绑定FTP到发送端上
$ns at $starttime "$ftp($src) start" #ftp包发送时间为starttime
}
if { "$val(traffic)" == "ftp" } { #如果当前数据流为ftp
puts "\nTraffic: ftp" #打印Traffic: ftp
puts [format "Acknowledgement for data: %s" [Mac/802_15_4 wpanCmd ack4data]]
#打印ack4data信息
$ns at $appTime1 "Mac/802_15_4 wpanNam PlaybackRate 0.20ms"#设置nam播放速度
$ns at [expr $appTime1 + 0.5] "Mac/802_15_4 wpanNam PlaybackRate 1.5ms"#同上
ftptraffic 0 1 $appTime1 #调用ftptraffic 函数,appTime1时节点0向1发送数据
ftptraffic 0 3 $appTime3 #调用ftptraffic 函数
ftptraffic 0 5 $appTime5 #调用ftptraffic 函数
$ns at $appTime1 "$ns trace-annotate \"(at $appTime1) ftp traffic from node 0 to node 1\"" #在nam中插入注释
$ns at $appTime3 "$ns trace-annotate \"(at $appTime3) ftp traffic from node 0 to node 3\"" #在nam中插入注释
$ns at $appTime5 "$ns trace-annotate \"(at $appTime5) ftp traffic from node 0 to node 5\"" #在nam中插入注释
Mac/802_15_4 wpanNam FlowClr -p AODV -c tomato #设置AODV数据包为tomato色
Mac/802_15_4 wpanNam FlowClr -p ARP -c green #设置ARP数据包为绿色
Mac/802_15_4 wpanNam FlowClr -p MAC -s 0 -d -1 -c navy #0-1节点MAC 包为绿色
Mac/802_15_4 wpanNam FlowClr -p tcp -s 0 -d 1 -c blue #0-1节点cp数据包为蓝色
Mac/802_15_4 wpanNam FlowClr -p ack -s 1 -d 0 -c blue #1-0节点ack 数据包为蓝色
Mac/802_15_4 wpanNam FlowClr -p tcp -s 0 -d 3 -c green4 #0-3节点tcp数据包为绿色
Mac/802_15_4 wpanNam FlowClr -p ack -s 3 -d 0 -c green4 #3-0节点ack 数据包为绿色
Mac/802_15_4 wpanNam FlowClr -p tcp -s 0 -d 5 -c cyan4 #0-5节点tcp数据包为青色
Mac/802_15_4 wpanNam FlowClr -p ack -s 5 -d 0 -c cyan4 #5-0节点ack数据包为青色
#定义一个结束的过程
proc stop {} {
global ns tracefd appTime1 val env #引用全局变量
$ns flush-trace #清除跟踪
close $tracefd #关闭追踪文件
set hasDISPLAY 0 #设置播放器为0
foreach index [array names env] {
if { ("$index" == "DISPLAY") && ("$env($index)" != "") } {
set hasDISPLAY 1 #设置播放器为1
}
}
if { ("$val(nam)" == "WPAN_MAC.nam") && ("$hasDISPLAY" == "1") } {
exec nam WPAN_MAC.nam & #以背景执行的方式去执行NAM
}
}
$ns at $stopTime "stop" #调用stop过程
$ns at $stopTime "puts \"NS EXITING...\n\"" #打印NS EXITING...
$ns at $stopTime "$ns halt" #调用halt
puts "\nStarting Simulation..." #打印Starting Simulation...
#开始仿真
$ns run