NS2 进行无线模拟时 调用的类和函数

来源:互联网 发布:小米预装软件卸载 编辑:程序博客网 时间:2024/05/22 03:24

      把一个tcl脚本中可以显式看到的类和函数写了出来,还有很多地方不是很理解,如果有人帮忙解答或改错,感激不尽

我的想法:

一般的方法都是在C++中定义的, OTcl一般通过unknown{},cmd{},调用C++comand{},然后在调用到C++的方法; 而直接在Otcl中定义方法的情况比较少见,但也不是没有

几点疑问:

                  很多tcl中的类没有类声明,我猜可能是隐藏了或运行时自动生成

         Node label方法我找了很久, 找不到是如何调用C++,command中找不到,只在net-interface.cc中看到有关”label”command()

关于调用父类同名函数的问题,是否需要显式的把调用父类的代码写出来,比如$cbr1 attach-agent $udp1,我是在Application类中找到的command()函数中有相关的代码,而在Application/Traffic/CBRApplication/Traffic中都没有command()函数,NS是否会自己向上代用

感想:

NS代码很多,对于一个学习的人来说理解起来很困难,我现在大概知道了tcl脚本运行时的流程,不过要进行内部协议和代码的编写还有一定困难,主要是对接口API了解不多以及NS的技术手册不可能写的很详细(东西太多了),只有针对要研究的方向,读相关的代码.

举例说明《移动IP技术与NS-2模拟》

9.2.2 无线网络中的UDP模拟Page 101

 

set val(proc) Propagation/TwoRayGround

set val(netif) Phy/WirelessPhy

set val(mac) Mac/802_11

set val(ifq) Queue/DropTail/PriQueue

set val(ll) LL

set val(ant) Antenna/OmniAntenna

set val(ifqlen) 50

set val(rp) DSDV

 

#tcl

#ns-lib.tcl

# Class Simulator 方法 Simulator instproc init args

#

#我没有找到解释层次的Simulator,只在ns-lib.tclLine128看到”#Class Simulator”

##Class Simulator

#...

#Simulator instproc init args {}

#

#C++

#Simulator.{h.cc}

#class Simulator      class SimulatorClass        方法 Simulator()

#

#class Simulator : public TclObject {}

 

#static class SimulatorClass : public TclClass {

#public:

#       SimulatorClass() : TclClass("Simulator") {}

#       TclObject* create(int argc, const char*const* argv) {

#                return (new Simulator);

#       }

#

#} simulator_class;

#

#      Simulator() : nodelist_(NULL), rtobject_(NULL), nn_(0), /

#       size_(0) {}

set ns_ [new Simulator] 

 

#tcl

#找不到

#

#C++

#topography.{h.cc}

# class Topography class TopographyClass 方法 Topography()

#

#class Topography : public TclObject {}

#

#static class TopographyClass : public TclClass {

#public:

#        TopographyClass() : TclClass("Topography") {}

#        TclObject* create(int, const char*const*) {

#                return (new Topography);

#        }

#} class_topography;

#

#       Topography() { maxX = maxY = grid_resolution = 0.0; grid = 0; }

set topo [new Topography]     

 

#tcl

# topography.cc

#Otcl的类是小于C++的类,这个tcl的实现是用unknown{},cmd{},command{}实现的

#

#int

#Topography::command(int argc, const char*const* argv)

#{

#      

#       else if(argc == 4) {

#                if(strcmp(argv[1], "load_flatgrid") == 0) {

#                          if(load_flatgrid(atoi(argv[2]), atoi(argv[3])))

#                                   return TCL_ERROR;

#                          return TCL_OK;

#                }

#       }

#       else if(argc == 5) {

#                if(strcmp(argv[1], "load_flatgrid") == 0) {

#                          if(load_flatgrid(atoi(argv[2]), atoi(argv[3]), atoi(argv[4])))

#                                   return TCL_ERROR;

#                          return TCL_OK;

#                }

#       }

#       return TclObject::command(argc, argv);

#}

#

#C++

#topography.{h.cc}

#方法 load_flatgrid ()

#

#int

#Topography::load_flatgrid(int x, int y, int res)

#{

#       /* No Reason to malloc a grid */

#

#       grid_resolution = res;      // default is 1 meter

#       maxX = (double) x;

#       maxY = (double) y;

#

#       return 0;

#}

$topo load_flatgrid 700 700   

 

set f [open 2-2.tr w]

 

#tcl

#ns-lib.tcl

# 方法 trace-all

#

#Simulator instproc trace-all file {

#       $self instvar traceAllFile_

#       set traceAllFile_ $file

#}

#

#C++

 

$ns_ trace-all $f

 

#tcl

#ns-lib.tcl

# 方法 eventtrace-all

#

#Simulator instproc eventtrace-all {{file ""}} {

#       $self instvar eventTraceAll_ eventtraceAllFile_ traceAllFile_

#       set eventTraceAll_ 1

#       if {$file != ""} {

#                set eventtraceAllFile_ $file

#       } else {

#                set eventtraceAllFile_ $traceAllFile_

#       }

#      

#}

#

#C++

 

$ns_ eventtrace-all

set nf [open 2-2.nam w]

 

#tcl

#ns-lib.tcl

# 方法 namtrace-all-wireless namtrace-all

#

#Simulator instproc namtrace-all-wireless {file optx opty} {

#        $self instvar namtraceAllFile_

#

#       # indicate that we need a W event written to the trace

#       $self set namNeedsW_ 1

#       if { $optx != "" && $opty != "" } {

#                $self set namWx_ $optx

#                $self set namWy_ $opty

#       }

#

#       $self namtrace-all $file

#}

#

#Simulator instproc namtrace-all file   {

#       $self instvar namtraceAllFile_

#       if {$file != ""} {

#                set namtraceAllFile_ $file

#       } else {

#                unset namtraceAllFile_

#       }

#}

#

#C++

 

$ns_ namtrace-all-wireless $nf

 

#tcl

#com.tcl

# Class God 方法 create-god{}

#

##Class God

#

#proc create-god { nodes } {

#       #global ns_ god_ tracefd

#       set god [God info instances]

#       if { $god == "" } {

#                set god [new God]

#       }

#       $god num_nodes $nodes

#       return $god

#}

#

#C++

#god.{h,cc}

# class God class GodClass

#数值2通过com.tcl中的num_nodes传给god.cc中的int num_nodes

#

# class God : public BiConnector {}

#

# static class GodClass : public TclClass {

#public:

#        GodClass() : TclClass("God") {}

#        TclObject* create(int, const char*const*) {

#                return (new God);

#        }

#} class_God;

create-god 2

 

#tcl

#ns-lib.tcl

#方法 node-config

#

#Simulator instproc node-config args {

#               

#        set args [eval $self init-vars $args]

#                ...

#}

#

#C++

#没有或者我不知道,我觉得是把每个变量的值用变量绑定的用法传给对应的C++中的变量

$ns_ node-config -adhocRouting $val(rp)/

         -llType $val(ll)/

         -macType $val(mac)/

         -ifqType $val(ifq)/

         -ifqLen $val(ifqlen)/

         -antType $val(ant)/

         -propType $val(prop)/

         -phyType $val(netif)/

         -channelType Channel/WirelessChannel/

         -topoInstance $topo/

         -agentTrace ON/

         -routerTrace OFF/

         -macTrace ON/

         -movementTrace OFF

 

#tcl

#ns-lib.tcl; ns-mobilenode.tcl

#方法 node; create-wireless-node; create-node-instance Node/MobileNode 方法 init

#

# Simulator instproc node args {

#            

#       # wireless-ready node

#       if { [info exists routingAgent_] && ($routingAgent_ != "") } {

#                set node [eval $self create-wireless-node $args]

#               

#                return $node

#       }

#            

#}

#

# Simulator instproc create-wireless-node args{

#      

#       set node [eval $self create-node-instance $args]

#      

#}

#

# Simulator instproc create-node-instance args {

#      

#       else {

#                set nodeclass Node/MobileNode

#       }

#       return [eval new $nodeclass $args]

#}

#

#Node/MobileNode instproc init args {

#      

#       eval $self next $args

#      

#}

#

#C++

#mobilenode.{h,cc}

# class MobileNode class MobileNodeClass 方法 MobileNode(void)

#

# class MobileNode : public Node {}

#

# static class MobileNodeClass : public TclClass {

#public:

#        MobileNodeClass() : TclClass("Node/MobileNode") {}

#        TclObject* create(int, const char*const*) {

#                return (new MobileNode);

#        }

#} class_mobilenode;

#

# MobileNode::MobileNode(void) : pos_handle_(this){}

set node_(0) [$ns_ node]

set node_(1) [$ns_ node]

 

#tcl

#tcl中没有label方法,然后我去查看对应的C++中的command方法,但是没有查到,凭感觉#是调用C++中的Node::label(),不过没有找到如何使Node::label()运行的command方法

#

#C++

#node.cc

#方法 label()

#

#void

#Node::label(const char* name, int anchor) {

#       delete []label_;

#       label_ = new char[strlen(name) + 1];

#       strcpy(label_, name);

#       anchor_ = anchor;

#}

$node_(0) label "Node 0"

$node_(0) set X_ 10.0

$node_(0) set Y_ 10.0

$node_(0) set Z_ 0.0

 

$node_(1) label "Node 1"

$node_(1) set X_ 600.0

$node_(1) set Y_ 600.0

$node_(1) set Z_ 0.0

 

#tcl

#找不到

#

#C++

#udp.{h,cc}

# class UdpAgent class UdpAgentClass 方法 UdpAgent(){}

# class UdpAgent : public Agent {}

#

#static class UdpAgentClass : public TclClass {

#public:

#       UdpAgentClass() : TclClass("Agent/UDP") {}

#       TclObject* create(int, const char*const*) {

#                return (new UdpAgent());

#       }

#} class_udp_agent;

#

#UdpAgent::UdpAgent() : Agent(PT_UDP), seqno_(-1)

#{

#       bind("packetSize_", &size_);

#}

set udp1 [new Agent/UDP]

 

#tcl

#ns-agent.tcl

# Class Agent/Null 方法 Agent/Null instproc init args{}

#

# Class Agent/Null -superclass Agent

#

#Agent/Null instproc init args {

#    eval $self next $args

#}

#

#C++

#没有,Otcl中的Agent/Null 继承于Agent,调用C++中类Agent的初始化

set null1 [new Agent/Null]

 

#tcl

#ns-lib.tcl, ns-node.tcl

#方法 attach-agent{} 方法attach{} 方法 add-target

#

# Simulator instproc attach-agent { node agent } {

#       $node attach $agent

#      

#}

#

#Node instproc attach { agent { port "" } } {

#      

#       $self add-target $agent $port

#}

#

# Node instproc add-target { agent port } {}

#

#C++

#没有

$ns_ attach-agent $node_(0) $udp1

$ns_ attach-agent $node_(1) $null1

 

#tcl

#ns-lib.tcl

#方法 connect{} 方法 simplex-connect{}

#

#Simulator instproc connect {src dst} {

#      

#       $self simplex-connect $src $dst

#       $self simplex-connect $dst $src

#      

#}

#

#Simulator instproc simplex-connect { src dst } {

#      

#       return $src

#}

#

#C++

#没有

$ns_ connect $udp1 $null1

 

#tcl

#找不到

#

#C++

#cbr_traffic.{h,cc}

# class CBR_Traffic class CBRTrafficClass 方法 CBR_Traffic()

#

# class CBR_Traffic : public TrafficGenerator {}

#

#static class CBRTrafficClass : public TclClass {

# public:

#       CBRTrafficClass() : TclClass("Application/Traffic/CBR") {}

#       TclObject* create(int, const char*const*) {

#                return (new CBR_Traffic());

#       }

#} class_cbr_traffic;

#

#CBR_Traffic::CBR_Traffic() : seqno_(0)

#{

#       bind_bw("rate_", &rate_);

#       bind("random_", &random_);

#       bind("packetSize_", &size_);

#       bind("maxpkts_", &maxpkts_);

#}

set cbr1 [new Application/Traffic/CBR]

 

#tcl

#ns-source.tcl

# 方法Application/Traffic/CBR instproc set args{}, Application/Traffic instproc set args{}

#

# Application/Traffic/CBR instproc set args {

#       $self instvar packetSize_ rate_

#       if { [lindex $args 0] == "interval_" } {

#                if { [llength $args] == 2 } {

#                          set ns_ [Simulator instance]

#                          set interval_ [$ns_ delay_parse [lindex $args 1]]

#                          $self set rate_ [expr $packetSize_ * 8.0/$interval_]

#                          return

#                } elseif { [llength $args] == 1 } {

#                          return [expr $packetSize_ * 8.0/$rate_]

#                }

#       }

#       eval $self next $args

#}

#

#Application/Traffic instproc set args {

#       $self instvar packetSize_ rate_

#       if { [lindex $args 0] == "packet_size_" } {

#                if { [llength $args] == 2 } {

#                          set packetSize_ [lindex $args 1]

#                          return

#                } elseif { [llength $args] == 1 } {

#                          return $packetSize_

#                }

#       }

##应该还会继续调用父类方法,可是我找不到Application instproc set args{}

#       eval $self next $args

#}

#

#C++

#没有

$cbr1 set rate_ 0.5Mb

$cbr1 set packetSize_ 200

 

#tcl

#app.cc

#通过unknown{},cmd{},command{}实现的

#

#int Application::command(int argc, const char*const* argv)

#{

#      

#       else if (argc == 3) {

#                if (strcmp(argv[1], "attach-agent") == 0) {

#                          agent_ = (Agent*) TclObject::lookup(argv[2]);

#                          if (agent_ == 0) {

#                                   tcl.resultf("no such agent %s", argv[2]);

#                                   return(TCL_ERROR);

#                          }

#                          agent_->attachApp(this);

#                          return(TCL_OK);

#                }

#               

#       }

#       return (Process::command(argc, argv));

#}

#

#C++

#tclcl.h

#方法 TclObject::lookup(),Tcl::instance().lookup(), …, Tcl::lookup()

#

# inline static TclObject* lookup(const char* name) {

#                return (Tcl::instance().lookup(name));

#       }

#

#      TclObject* Tcl::lookup(const char* name)

#{

#       /*XXX use tcl hash table */

#       Tcl_HashEntry* he = Tcl_FindHashEntry(&objs_, (char*)name);

#       if (he != 0)

#                return ((TclObject*)Tcl_GetHashValue(he));

#       return (0);

#}

$cbr1 attach-agent $udp1

 

#tcl

#ns-lib.tcl

#方法 Simulator instproc at args{}

#

# Simulator instproc at args {

#       $self instvar scheduler_

#       return [eval $scheduler_ at $args]

#}

#

#C++

#没有

#

#tcl

#app.cc

#通过unknown{},cmd{},command{}实现的

#

# int Application::command(int argc, const char*const* argv)

#{

#       Tcl& tcl = Tcl::instance();

#

#       if (argc == 2) {

#                if (strcmp(argv[1], "start") == 0) {

#                          // enableRecv_ only if recv() exists in Tcl

#                          tcl.evalf("[%s info class] info instprocs", name_);

#                         char result[1024];

#                          sprintf(result, " %s ", tcl.result());

#                          enableRecv_ = (strstr(result, " recv ") != 0);

#                          enableResume_ = (strstr(result, " resume ") != 0);

#                          start();

#                          return (TCL_OK);

#                }

#               

#       }

#      

#       return (Process::command(argc, argv));

#}

#

#C++

#app.cc

#方法start()

#

# void Application::start(){}

#

# void CBR_Traffic::start()

#{

#        init();

#        running_ = 1;

#        timeout();

#}

$ns_ at 5.0 "$cbr1 start"

 

#tcl

#ns-node.tcl

#方法reset{}, list-modules {}

#

#Node instproc reset {} {

#       $self instvar agents_

#       foreach a $agents_ {

#                $a reset

#       }

#       foreach m [$self list-modules] {

#                $m reset

#       }

#}

#

#Node instproc list-modules {} {

#       $self instvar reg_module_

#       set ret ""

#       foreach n [array names reg_module_] {

#                lappend ret $reg_module_($n)

#       }

#       return $ret

#}

#

#C++

#有可能调用agent instproc reset 若没有, 则调用class agentcommand(), 不过我找了这两#个地方没找到,所以我觉得有可能要看是具体哪个agent,然后调用agent的子类的#command()

$ns_ at 0.0 "$node_(0) reset"

$ns_ at 0.0 "$node_(1) reset"

 

#tcl

#mobilenode.cc

#通过unknown{},cmd{},command{}实现的

#

#int

#MobileNode::command(int argc, const char*const* argv)

#{

#      

#       else if (argc == 5) {

#                if (strcmp(argv[1], "setdest") == 0) {

#                          /* <mobilenode> setdest <X> <Y> <speed> */

##ifdef DEBUG

#                          fprintf(stderr, "%d - %s: calling set_destination()/n",

#                                   address_, __FUNCTION__);

##endif

#

#                          if (set_destination(atof(argv[2]), atof(argv[3]),

#                                                atof(argv[4])) < 0)

#                                   return TCL_ERROR;

#                          return TCL_OK;

#                }

#       }

#       return Node::command(argc, argv);

#}

#

#C++

#mobilenode.cc

#方法 MobileNode::set_destination()

#

#int

MobileNode::set_destination(double x, double y, double s)

{

         assert(initialized());

 

         if(x >= T_->upperX() || x <= T_->lowerX())

                   return -1;

         if(y >= T_->upperY() || y <= T_->lowerY())

                   return -1;

        

         update_position();   // figure out where we are now

        

         destX_ = x;

         destY_ = y;

         speed_ = s;

        

         return 0;

}

$ns_ at 0.6 "$node_(0) setdest 300.0 250.0 60.0"

$ns_ at 1.1 "$node_(1) setdest 300.0 300.0 60.0"

$ns_ at 40 "$node_(0) setdest 600.0 600.0 20.0"

$ns_ at 40.1 "$node_(1) setdest 100.0 100.0 20.0"

 

$ns_ at 50.0 "finish"

 

#tcl

#ns-lib.tcl

# 方法Simulator instproc halt {}

#

#Simulator instproc halt {} {

#       $self instvar scheduler_

#       #puts "time: [clock format [clock seconds] -format %X]"

#       $scheduler_ halt

#}

#

#C++

#scheduler.{h,cc}

#方法 command()

#

# int

#Scheduler::command(int argc, const char*const* argv)

#{

#      

#                else if (strcmp(argv[1], "halt") == 0) {

#                          halted_ = 1;

#                          return (TCL_OK);

#

#                }

#      

#}

$ns_ at 50.1 "puts /"NS EXITING.../"; $ns_ halt"

 

proc finish {} {

         global ns_ f nf val

         $ns_ flush-trace

         close $f

         close $nf

}

 

puts "Starting Simulation..."

 

#tcl, C++

#ns-lib.tcl, priqueue.cc, ns-namsupp.tcl, scheduler.cc

#方法 Simulator instproc run {}, 这其中做了一系列初始化check-smac{}, check-node-num{}, #rtmodel-configure{}, get-routelogic{}…(若这些不在Simulator instproc中定义,那就是通过#command()C++中定义的);

#Node instproc reset{};

#Queue reset 通过command传给PriQueue::command()来执行; 然后调用了Terminate()

#Simulator instproc init-nam {}; s

#scheduler run通过command传给Scheduler::command()中定义的,然后调用了reset(); run()

#

# Simulator instproc run {} {

#      

#       foreach nn [array names Node_] {

#                $Node_($nn) reset

#               

#                }

#       }

#      

#       foreach qn [array names link_] {

#                set q [$link_($qn) queue]

#                $q reset

#       }

#      

#       $self init-nam

#      

#       return [$scheduler_ run]

#}

#

#int

#PriQueue::command(int argc, const char*const* argv)

#{

#  if (argc == 2 && strcasecmp(argv[1], "reset") == 0)

#   {

#      Terminate();

#      //FALL-THROUGH to give parents a chance to reset

#    }

#  return DropTail::command(argc, argv);

#}

#

#Simulator instproc init-nam {} {

#       #一系列初始化

#      

#}

#

#int

#Scheduler::command(int argc, const char*const* argv)

#{

#      

#       if (argc == 2) {

#                if (strcmp(argv[1], "run") == 0) {

#                          /* set global to 0 before calling object reset methods */

#                          reset();     // sets clock to zero

#                          run();

#                          return (TCL_OK);

#                }

$ns_ run