您的位置:首页 > 理论基础 > 计算机网络

ns-2与TCP拥塞模拟 之七 ns-2中自带的应用Ping解读

2015-10-06 21:48 633 查看


ns-2与TCP拥塞模拟 之七
ns-2中自带的应用Ping解读


以ns-2中自带的应用Agent/Ping为例,描述一下如何编写一个“应用”。下面引用的是版本2.35中的代码,其他版本可能略有差异。以下是需要注意的地方:

(1)头文件.h中声明的类属性和方法;

(2)Tcl脚本的变量与C++类的变量的绑定;

(3)C++类中的command函数是Agent类与Tcl的接口(Tcl脚本的命令直接作用于该函数);

(4)C++类中的recv函数,是Agent类功能实现的关键,网络中对于数据包的分类、转发和处理的操作都是通过这个函数来实现的;

(5)TclClass的编写与修改,为Tcl脚本提供接口。

具体的实践过程可以按照以下4个主要步骤进行,举例如下。

(1)添加头文件ns-2.35/apps/ping.h。

/*

* File:Header File for a new 'Ping' Agent Class for the ns

*
network simulator


*Author: Marc Greis (greis@cs.uni-bonn.de), May 1998

*/

#ifndef ns_ping_h

#define ns_ping_h

#include "agent.h"

#include "tclcl.h"

#include "packet.h"

#include "address.h"

#include "ip.h"

struct hdr_ping {



charret;
//从源端出来时值为 0,从目的端回来时值为
1;



doublesend_time;
//源端发送的时间戳,用于往返时延的计算;



doublercv_time;

//接收时刻



intseq;

//序列号



//Header access methods



staticint offset_;
//偏移量



inlinestatic int& offset() { return offset_; }



inlinestatic hdr_ping* access(const Packet* p) {



return(hdr_ping*) p->access(offset_);



}


};

class PingAgent : public Agent {

public:


PingAgent();



intseq;

//发送序号



intoneway;

//标志位



virtualint command(int argc, const char*const* argv);



virtualvoid recv(Packet*, Handler*);


};

#endif // ns_ping_h

(2)添加代码文件ns-2.35/apps/ping.cc。

/*

* File:Code for a new 'Ping' Agent Class for the ns

*
network simulator


*Author: Marc Greis (greis@cs.uni-bonn.de), May 1998

*/

#include "ping.h"

int hdr_ping::offset_;

//以下的两个静态类定义主要完成C++和OTcl的连接


static class PingHeaderClass : publicPacketHeaderClass {

public:


PingHeaderClass(): PacketHeaderClass("PacketHeader/Ping",



sizeof(hdr_ping)) {



bind_offset(&hdr_ping::offset_);



}


} class_pinghdr;

static class PingClass : public TclClass {

public:


PingClass(): TclClass("Agent/Ping") {}



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



return(new PingAgent());



}


} class_ping;

PingAgent::PingAgent() : Agent(PT_PING),seq(0), oneway(0)
//PingAgent的构造函数


{


bind("packetSize_",&size_);


}

int PingAgent::command(int argc, constchar*const* argv)

{


if(argc == 2) {



if(strcmp(argv[1], "send") == 0) { //如:$p0
send,作为command
函数的输入



//Create a new packet


Packet* pkt = allocpkt();


//Access the Ping header for the new packet:


hdr_ping* hdr = hdr_ping::access(pkt);


//Set the 'ret' field to 0, so the receiving node



//knows that it has to generate an echo packet



hdr->ret = 0;



hdr->seq = seq++;



// Store thecurrent time in the 'send_time' field


hdr->send_time = Scheduler::instance().clock();


//Send the packet


send(pkt, 0);


//return TCL_OK, so the calling function knows that



//the command has been processed


return (TCL_OK);


}



elseif (strcmp(argv[1], "start-WL-brdcast") == 0) {


Packet* pkt = allocpkt();

hdr_ip* iph = HDR_IP(pkt);

hdr_ping* ph = hdr_ping::access(pkt);


iph->daddr() = IP_BROADCAST;


iph->dport() = iph->sport();


ph->ret = 0;



send(pkt, (Handler*) 0);



return (TCL_OK);



}



elseif (strcmp(argv[1], "oneway") == 0) {


oneway=1;

return (TCL_OK);


}



}



// Ifthe command hasn't been processed by PingAgent()::command,



//call the command() function for the base class



return(Agent::command(argc, argv));


}

void PingAgent::recv(Packet* pkt, Handler*)

{


//Access the IP header for the received packet:



hdr_ip*hdrip = hdr_ip::access(pkt);



//Access the Ping header for the received packet:


hdr_ping* hdr = hdr_ping::access(pkt);


//check if in brdcast mode



if((u_int32_t)hdrip->daddr() == IP_BROADCAST) {



if(hdr->ret == 0) {


printf("Recv BRDCAST Ping REQ : at %d.%d from %d.%d\n",here_.addr_, here_.port_,
hdrip->saddr(), hdrip->sport());


Packet::free(pkt);


//create reply


Packet* pktret = allocpkt();

hdr_ping* hdrret = hdr_ping::access(pktret);


hdr_ip* ipret = hdr_ip::access(pktret);


hdrret->ret = 1;


//add brdcast address


ipret->daddr() = IP_BROADCAST;


ipret->dport() = ipret->sport();



send(pktret, 0);



} else {


printf("Recv BRDCAST Ping REPLY : at %d.%d from %d.%d\n",here_.addr_, here_.port_,
hdrip->saddr(), hdrip->sport());


Packet::free(pkt);


}


return;


}



// Isthe 'ret' field = 0 (i.e. the receiving node is being pinged)?



if(hdr->ret == 0) {



//Send an 'echo'. First save the old packet's send_time


double stime = hdr->send_time;


intrcv_seq = hdr->seq;



//Discard the packet


Packet::free(pkt);


//Create a new packet


Packet* pktret = allocpkt();


//Access the Ping header for the new packet:


hdr_ping* hdrret = hdr_ping::access(pktret);


//Set the 'ret' field to 1, so the receiver won't send



//another echo


hdrret->ret = 1;


//Set the send_time field to the correct value


hdrret->send_time = stime;


//Added by Andrei Gurtov for one-way delay measurement.


hdrret->rcv_time = Scheduler::instance().clock();

hdrret->seq = rcv_seq;


//Send the packet


send(pktret, 0);


} else{



// Apacket was received. Use tcl.eval to call the Tcl



//interpreter with the ping results.



//Note: In the Tcl code, a procedure



//'Agent/Ping recv {from rtt}' has to be defined which



//allows the user to react to the ping result.



charout[100];



//Prepare the output to the Tcl interpreter. Calculate the



//round trip time



if(oneway) //AG



sprintf(out,"%s recv %d %d %3.1f %3.1f", name(),



hdrip->src_.addr_ >>Address::instance().NodeShift_[1],



hdr->seq, (hdr->rcv_time -hdr->send_time) * 1000,



(Scheduler::instance().clock()-hdr->rcv_time)* 1000);



elsesprintf(out, "%s recv %d %3.1f",name(),



hdrip->src_.addr_ >>Address::instance().NodeShift_[1],



(Scheduler::instance().clock()-hdr->send_time)* 1000);


Tcl& tcl = Tcl::instance();


tcl.eval(out);



//Discard the packet


Packet::free(pkt);


}


}

以上代码的逻辑比较清晰明了,可以看出,比较重要的是command函数中处理“send”命令的部分和recv函数。


函数command中处理“send”命令的部分,在逻辑上是发送端,发送第一个报文分组。


函数recv中结构“if(hdr->ret
== 0) {…}”部分,逻辑上是接收端处理收到的分组;填充了一个新的报文分组的标志、时间戳、序号等部分后,发送了这个响应包;当然,这个recv函数比较复杂的部分是考虑了广播包和双向反馈。

(3)ns-2中应该做的其他必要修改。


修改ns-2.35/common/packet.h文件。



// RAP packets

static const packet_t PT_RAP_DATA = 40;

static const packet_t PT_RAP_ACK = 41;

static const packet_t PT_TFRC = 42;

static const packet_t PT_TFRC_ACK = 43;

static const packet_t PT_PING = 44;

static const packet_t PT_PBC = 45;

// Diffusion packets - Chalermek

static const packet_t PT_DIFF = 46;



class p_info {





staticvoid initName()



{



if(nPkt_>= PT_NTYPE+1)



return;





name_[PT_TFRC]="tcpFriend";



name_[PT_TFRC_ACK]="tcpFriendCtl";



name_[PT_PING]="ping";



name_[PT_PBC]= "PBC";





}


}


修改ns-2.35/tcl/lib/ns-default.tcl文件。



##Agent set seqno_ 0 now is gone

##Agent set class_ 0 now is gone

Agent/Ping set packetSize_ 64

Agent/UDP set packetSize_ 1000

Agent/UDP instproc done {} { }

Agent/UDP instproc process_data {from data} {}




修改ns-2.35/tcl/lib/ns-packet.tcl文件。

set protolist {



# Application-Layer Protocols:


Message # a protocol to carry text messages



Ping
# Ping



PBC # PBC




}


修改ns-2.35/Makefile文件。

OBJ_CC = \


tools/random.otools/rng.o tools/ranvar.o common/misc.o common/timer-handler.o \





tcp/tfrc.otcp/tfrc-sink.o mobile/energy-model.o apps/ping.o tcp/tcp-rfc793edu.o \




执行make
命令。

(4)运行以下ping.tcl
进行测试。

#ping.tcl
文件


#Create a simulator object

set ns [new Simulator]

#Open a trace file

set tracefd [open out.tr w]

$ns trace-all $tracefd

set nf [open out.nam w]

$ns namtrace-all $nf

#Define a 'finish' procedure

proc finish {} {

global ns nf

$ns flush-trace

close $nf

exec nam out.nam &

exit 0

}

#Create three nodes

set n0 [$ns node]

set n1 [$ns node]

set n2 [$ns node]

#Connect the nodes with two links

$ns duplex-link $n0 $n1 1Mb 10ms DropTail

$ns duplex-link $n1 $n2 1Mb 10ms DropTail

#Create two ping agents and attach them to thenodes n0 and n2

set p0 [new Agent/Ping]

$ns attach-agent $n0 $p0

set p1 [new Agent/Ping]

$ns attach-agent $n2 $p1

#Connect the two agents

$ns connect $p0 $p1

#Schedule events

$ns at 0.2 "$p0send"

$ns at 0.4 "$p1send"

$ns at 0.6 "$p0send"

$ns at 0.6 "$p1send"

$ns at 1.0 "finish"

#Run the simulation

$ns run

整体上来看,与代理模块相比,添加一个新的“应用”,需要在合适的Tcl文件中添加相应的报文类型定义。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: