📄 ns-rca.tcl
字号:
# Message Type Constantsset ADV 0set REQ 1set DATA 2set RESEND 3set MAC_BROADCAST 0xffffffffset LINK_BROADCAST 0xffffffffClass Application/RCApp -superclass Application############################################################################## Miscellaneous functions############################################################################## RcApp::init## This function initializes the application and all variables associated# with it.set index 0Application/RCApp instproc init {md_class wantslist haslist} { global hasarray index $self instvar packetMsg_ $self instvar stats_ $self instvar adv_threshold_ $self instvar pending_delay_ $self instvar rng_ $self instvar has_ wants_ pending_ md_class_ $self instvar advlist_ $self instvar neighbors_ $self instvar init_wants_ $self instvar advert_period_ $self instvar already_sent_data_ $self instvar resend_timeout_ # initilizations set md_class_ $md_class set has_ [new $md_class] $has_ addlist $haslist set wants_ [new $md_class] $wants_ addlist $wantslist set init_wants_ [$wants_ copy] set pending_ [new $md_class] set advlist_ [new Advlist] set already_sent_data_ [new $md_class] set resend_timeout_ .2 $wants_ subtract $has_ set hasarray($index) $has_ incr index set stats_ [new RCStats] set packetMsg_ 0 set adv_threshold_ 0 set pending_delay_ .4 set advert_period_ .4 set neighbors_ [new Set/KeySet] set rng_ [new RNG] $rng_ seed 0 $self next}# RcApp::getER## This function returns the EnergyResource # Application/RCApp instproc getER {} { set er [[[$self agent] set node_] getER] return $er}# RcApp::log## Send a comment to the log# Application/RCApp instproc log {msg} { [$self agent] log $msg}# RcApp::log-acquired## Send a comment to the log# Application/RCApp instproc log-acquired {has} { $self instvar init_wants_ set id [[[$self agent] set node_] id] set hassize [$has maptosize] set wantssize [$init_wants_ maptosize] if {$wantssize} { set percent [expr ($hassize + 0.0) / $wantssize] } else { set percent 0 } set msg "$id has = $percent" $self log $msg}# RcApp::start## This function will start data exchanges between the nodes# Application/RCApp instproc start {} { global ADV DATA MAC_BROADCAST LINK_BROADCAST ns_ $self instvar has_ adv_threshold_ advert_id_ advert_period_ # Decide whether have enough energy to ADV data # Note: if data is ADV'd, node must send the data set adv_meta [$self decideADV $has_] if {![$adv_meta emptyset?]} { set datasize [$adv_meta maptosize] set copy_meta [$adv_meta copy] if {$datasize <= $adv_threshold_} { $self send $MAC_BROADCAST $LINK_BROADCAST $DATA $copy_meta $datasize } else { $self send_meta $MAC_BROADCAST $LINK_BROADCAST $ADV $copy_meta } } else { set nodeID [[[$self agent] set node_] id] puts "Node $nodeID decided NOT to ADV has_ = [$has_ metatostring]" } $adv_meta destroy return}# RcApp::stop## This function stops data exchanges between the nodes# Application/RCApp instproc stop {} { puts "Stopping RCApp..." [$self agent] close}############################################################################## Receiving functions############################################################################## RcApp::recv## This function handles packets. It picks out the packet header,# and dispatches to other functions, based on the type of the message.# Application/RCApp instproc recv {args} { global ADV REQ DATA RESEND ns_ opt $self instvar md_class_ stats_ neighbors_ rng_ advlist_ has_ if {[llength $args] < 2} { puts "Error: RCApp receive function called with too few args" return } # Get the size and the string out of the arg list set link_dst [lindex $args 0] set sender [lindex $args 1] set data_size [lindex $args 2] set meta_string [lrange $args 3 end] # Add the sender to the list of known neighbors $neighbors_ add $sender # The type is stored internally set msg_type [[$self agent] set packetMsg_] # Convert the meta-data string into a data-structure set meta_data [new $md_class_] $meta_data stringtometa $meta_string set nodeID [[[$self agent] set node_] id] set senderID $sender set msg [lindex [list ADV REQ DATA RESEND] $msg_type] puts "\nNode $nodeID received $msg ($meta_string) from Node $senderID to $link_dst. Data size is $data_size." $neighbors_ pp "Neighbors now" # Dispatch based on type if {$msg_type == $ADV} { # Add meta_data and sender to advlist_ # This list keeps track of ADVs and who sent the ADV. O/w # could get an REQ for data which this node cannot receive b/c # it is outside the transmission area of the sending node, e.g.: # A --> B C : A sends ADV, but only B hears # A <-- B --> C : B sends REQ, both A and C hear REQ # A --> B C : A sends DATA, but only B hears # In this situation, C should not place meta-data REQd by B # on pending list, since data will not be heard by C! $advlist_ addADV $sender $meta_data if {[$meta_data subset $has_]} { # We do nothing puts "\n Node $nodeID already has advertised data. We do nothing." $meta_data destroy return } # There is a 3 ms delay between sending and receiving an REQ # Waiting time should be R=N*D to achieve E[dup] = 1 set D 3 set N [$self count_duplicates $meta_data] if {$N < 3} { set N 5 } set delay_bound [expr $D * $N] set delay [$rng_ uniform 0 $delay_bound] set delay_ms [expr $delay * .001] set random_delay [expr [$ns_ now] + $delay_ms] $ns_ at $random_delay "$self recvADV $link_dst $sender $meta_data" } elseif {$msg_type == $REQ} { $self recvREQ $link_dst $sender $meta_data } elseif {$msg_type == $RESEND} { $self recvRESEND $sender $meta_data } elseif {$msg_type == $DATA} { $self recvDATA $link_dst $sender $meta_data $data_size }}# RcApp::recvADV ## This function handles an ADV message. It updates# "wants" using the received meta-data. It then sends out a request# based on the intersection of "wants" and the advertisement. This# function takes care of freeing the meta-data by freeing the data# itself, or calling another function that frees the meta-data.Application/RCApp instproc recvADV {link_dst sender meta_data} { global ns_ REQ ADV MAC_BROADCAST $self instvar wants_ has_ stats_ pending_ pending_delay_ set nodeID [[[$self agent] set node_] id] puts "Node $nodeID recvADV $link_dst $sender [$meta_data metatostring]: at [$ns_ now]" $stats_ update_rcvs $sender $ADV [$meta_data numelements] 0puts "meta-data = [$meta_data metatostring], pending = [$pending_ metatostring], has = [$has_ metatostring]" # Subtract what is already pending from the meta-data $meta_data subtract $pending_ # Now subtract what we have out of the remaining meta-data $meta_data subtract $has_ set finalsize [$meta_data numelements] $stats_ update_useful $sender $ADV $finalsize 0 # If the meta-data contains_ nothing we want, stop. if {[$meta_data emptyset?]} { puts "Node $nodeID does not have any data to request from Node $sender" $meta_data destroy return } # Find the union of wants with the meta-data $wants_ union $meta_data # Decide whether to REQ data set req_meta [$self decideREQ $meta_data] if {![$req_meta emptyset?]} { puts "Now sending an REQ back to $sender" # Set this meta data to ageout from the pending list set metastring [$req_meta metatostring] $ns_ at [expr [$ns_ now] + $pending_delay_] "$self ageout_pending $sender \"$metastring\"" # Add the meta-data to the pending set $pending_ union $req_meta # Now send a request back to the sender for this meta-data set copy_meta [$req_meta copy] $self send_now $MAC_BROADCAST $sender $REQ $copy_meta 0 } else { puts "Application not requesting data [$meta_data metatostring]." } $req_meta destroy $meta_data destroy}# RCApp::recvREQ## This function handles an REQ message. Map the data described in the# meta-data to actual data, and send it back to the sender using a DATA# message. This function takes care of freeing the meta-data by freeing# the data itself, or calling another function that frees the meta-data.Application/RCApp instproc recvDirectREQ {sender meta_data} { global DATA REQ MAC_BROADCAST LINK_BROADCAST ns_ $self instvar has_ stats_ already_sent_data_ advlist_ $self instvar pending_delay_ resend_timeout_ puts "I just received a direct request for data [$meta_data metatostring]. I've already sent: [$already_sent_data_ metatostring]." # Figure out how much of this data we actually possess set meta_we_have [$meta_data copy] # Send the data if we possess it $meta_we_have intersection $has_ if {[$meta_we_have emptyset?]} { set nodeID [[[$self agent] set node_] id] puts "Node $nodeID does not have data requested by Node $sender" $meta_we_have destroy $meta_data destroy return } $meta_we_have subtract $already_sent_data_ if {[$meta_we_have emptyset?]} { puts "We've recently sent data [$meta_we_have metatostring] requested by Node $sender. Not sending." $meta_data destroy $meta_we_have destroy return } # Now figure out how large a message would be if we sent it set datasize [$meta_we_have maptosize] set copy_meta [$meta_we_have copy] # Keep track of what data has already been sent and do not # re-broadcast message # NOTE: we need to add a time-out for this list! $already_sent_data_ union $meta_we_have set metastring [$copy_meta metatostring] puts "Sending out data $metastring" $ns_ at [expr [$ns_ now] + $resend_timeout_] "$self resend_timeout \"$metastring\"" $self send_now $MAC_BROADCAST $LINK_BROADCAST $DATA $copy_meta $datasize $meta_data destroy $meta_we_have destroy}Application/RCApp instproc recvIndirectREQ {link_dst sender meta_data} { global DATA REQ MAC_BROADCAST LINK_BROADCAST ns_ $self instvar has_ stats_ already_sent_data_ pending_ advlist_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -