zoukankan      html  css  js  c++  java
  • 向NS2中添加协议PING

    在NS2中增加自己的协议模块一般分一下几个步骤:

    (1)       添加协议类

    (2)       定义协议分组头结构

    (3)       编译代码

    其实在ns3.35版本中已经有ping协议,此步骤只是为了了解ns2添加协议的一般步骤。

    1、  在ping协议中,需要定义自己的控制分组,因此首先需要在ping.h头文件中定义ping的分组头结构,C++代码如下:

    //在ping协议中定义自己的控制分组

    struct hdr_ping {

      char ret;       //0:从发送者到接收者,1:从接受者到发送者

      double send_time;   //发送时间,为了计算RTT

    };

    class PingAgent : public Agent {

     public:

      PingAgent();

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

      void recv(Packet*, Handler*);

     protected:

      int off_ping_;

    };

    2、ping需要被NS-2所接受并且可以在OTcl代码中使用,需要在ping.cc中定义如下代码:

    static class PingHeaderClass : public PacketHeaderClass {

    public:

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

                       sizeof(hdr_ping)) {}

    } class_pinghdr;

    本代码实现了OTcl中的PingHead/ping类与C++中的hdr_ping绑定在一起,这样定义出的分组头为Ping。

    2、 在~ns/tcl/lib/ns-packet.tcl中包含了系统中所有已实现的协议分组头名字,我们也需要在其中添加包头的名字Ping。

    Foreach {

            IVS

             QS

             …

             Ping

    }

    3、 为了创建ping分组,需要定义ping的分组类型。需要修改ns/common/packet.h文件:首先在emun packet中新增包类型:PT_PING;

    Enum packet_t {

      PT_TCP,

      PT_UDP,

      …

      PT_PING

    }

    然后在class p_info类的构造函数中定义新增包类型的名字:

    Class p_info {

    Public:

    P_info {

    name_[PT_TCP]=”tcp”;

    ……

    name_[PT_PIING]="ping";

     }

    ……

    4、 需要从TclCL继承一个PingClass类,其构造函数通过调用基类的构造函数“TclClass(”Agent/Ping”)”指定其对应的OTcl对象为Agent/Ping,这实际是做了登记工作,在ping.cc中定义:

    static class PingClass : public TclClass {

    public:

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

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

        return (new PingAgent());

      }

    } class_ping;

    OTcl代码:

    set p0 [new Agent/Ping]

    $ns attach-agent $n0 $p0

    当执行set p0 [new Agent/Ping]时,就会调用父类的构造函数(init方法),父类SplitObject调用create-shadow方法来登记OTcl对象p0和被创建的C++对象class_ping的关系。根据登记关系去调用TclObject* create(int, const char*const*)创建并返回对象指针:return (new PingAgent());

    5、 需要在PingAgent的构造函数中,需要将新创建的分组类型传递给Agent类的构造函数,因为PingAgent父类的构造函数中就需要定制分组类型作为参数。在PingAgent构造函数中实现C++和OTcl之间成员变量的绑定。

    PingAgent::PingAgent() : Agent(PT_PING)

    {

      bind("packetSize_", &size_);

      bind("off_ping_", &off_ping_);

    }

    变量绑定后,Agent/Ping类对象p0的成员变量packetSize_和off_ping_的变量在任何时候都和C++对象的成员变量保持一致。为了给这些变量初始化,需要在~ns/tcl/lib/ns-default.tcl中添加以下代码:

    Agent/Ping set packetSize 0

    Agent/Ping set off_ping_ 0

    ns-default.tcl这个文件是在Tcl脚本运行之前被执行的,所以在创建对象并在绑定变量时,变量已经进行了初始化。

    6、当执行

    $ns at 0.2 "$p0 send"

    C++对象的指针根据过程函数名去调用command函数,如下:

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

    {

      if (argc == 2) {

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

          // Create a new packet

          Packet* pkt = allocpkt();

          // Access the Ping header for the new packet:

          hdr_ping* hdr = (hdr_ping*)pkt->access(off_ping_);

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

          // that it has to generate an echo packet

          hdr->ret = 0;

          // Store the current 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);

        }

      }

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

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

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

    }

    6、 完成ping协议的定义和实现后,把ping.hh和ping.cc放在~ns/ping下,然后重新编译NS-2,把ping协议嵌入到NS-2代码中去,我们需要修改~ns/Makefile文件。

    在Makefile的OBJ_CC中,增加以下代码:ping/ping.o

    在ns目录下:make clean和make,完成编译。

    7、 ping.cc中的recv函数代码如下:

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

    {

      // Access the IP header for the received packet:

      hdr_ip* hdrip = (hdr_ip*)pkt->access(off_ip_);

      // Access the Ping header for the received packet:

      hdr_ping* hdr = (hdr_ping*)pkt->access(off_ping_);

      // Is the '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;

        // 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*)pktret->access(off_ping_);

        // 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;

        // Send the packet

        send(pktret, 0);

      } else {

        // A packet 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.

        char out[100];

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

        // trip time

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

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

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

        Tcl& tcl = Tcl::instance();

        tcl.eval(out);

        // Discard the packet

        Packet::free(pkt);

      }

    }

     8、TCL测试脚本如下:

    #Create a simulator object

    set ns [new Simulator]

     

    #Open a trace file

    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

     

    #Define a 'recv' function for the class 'Agent/Ping'

    Agent/Ping instproc recv {from rtt} {

        $self instvar node_

        puts "node [$node_ id] received ping answer from

                  $from with round-trip-time $rtt ms."

    }

     

    #Create two ping agents and attach them to the nodes 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 "$p0 send"

    $ns at 0.4 "$p1 send"

    $ns at 0.6 "$p0 send"

    $ns at 0.6 "$p1 send"

    $ns at 1.0 "finish"

     

    #Run the simulation

    $ns run

     

     

    http://www.cnblogs.com/ManMonth/archive/2011/03/15/1985518.html

  • 相关阅读:
    月亮的背后
    2007经典妙语100句
    2007经典妙语100句
    VS C++ 2005的预生成事件及设置
    user case VS. user story
    如何用正确的方法来写出质量好的软件的75条体会
    用 Lucene 加速 Web 搜索应用程序的开发
    巾帼不让须眉——女生做运维 interesting topic
    ebean
    Download the 2.0.0 Release of the Scala IDE for Eclipse Scala IDE for Eclipse
  • 原文地址:https://www.cnblogs.com/xlchen/p/4353857.html
Copyright © 2011-2022 走看看