原文地址:http://www.cnblogs.com/xyl-share-happy/archive/2012/03/20/2407732.html

------------------------------------------

在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

向NS2中添加协议PING[转载]相关推荐

  1. 向NS2中添加协议PING

    在NS2中增加自己的协议模块一般分一下几个步骤: (1)       添加协议类 (2)       定义协议分组头结构 (3)       编译代码 其实在ns3.35版本中已经有ping协议,此步 ...

  2. NS各种常用资料 [转载]

    (一). NS常用基本网站 1. Maillist个人觉得是寻求问题答案最好的地方. http://mailman.isi.edu/pipermail/ns-users/ 2. 柯老师的网站,包含很多 ...

  3. VC++中把一个对话框最小化到托盘[转载]

    From: http://hi.baidu.com/maxlcl/blog/item/61e83c87de35e529c65cc3e0.html 一.托盘简介 所谓的"托盘",在W ...

  4. [转载]iOS开发之第三方登录QQ

    转载自 iOS_developer_zhong 1. 申请腾讯开发账号. 地址:点击打开链接 2. 下载最新的SDK   地址: SDK下载 SDK内容如下: 1.sample 这个是简单的demo ...

  5. [转载]Java-集合框架完全解析

    在简书上看到一篇介绍Java集合框架的文章,写得挺详细的,http://www.jianshu.com/p/63e76826e852这是原文地址. 数据结构是以某种形式将数据组织在一起的集合,它不仅存 ...

  6. [转载]Linux SWAP 交换分区配置说明

    转自:http://blog.csdn.net/tianlesoftware/article/details/8741873 一.SWAP 说明 1.1 SWAP 概述 当系统的物理内存不够用的时候, ...

  7. Linux内核态之间进程通信,Linux 系统内核空间与用户空间通信的实现与分析[转载]...

    [https://www.ibm.com/developerworks/cn/linux/l-netlink/index.html] 多数的 Linux 内核态程序都需要和用户空间的进程交换数据,但 ...

  8. [转载]信息安全从业参考

    你可以转载本文,但请务必保留本文的完整性 Author: 赵彦,http://blog.sina.com.cn/u/1258699773 Homepage:http://www.ph4nt0m.org ...

  9. [转载]梯度下降小结

    转自:https://www.cnblogs.com/pinard/p/5970503.html 在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采 ...

最新文章

  1. java 括号匹配_java---括号匹配
  2. Linux / sudo、su、sudo su、sudo -i 使用和区别
  3. CRM One Order Appointment里start Date的存储原理
  4. centos 新建swap区文件
  5. 子窗体中组合框联动_一张表实现组合框联动
  6. 主进程中发生javascript错误_你知道 JavaScript 中的错误对象有哪些类型吗?
  7. 消息队列应用场景解析
  8. 微课|中学生可以这样学Python(例11.4):tkinter版图片查看器
  9. 一个简单的实现了智能虚拟女友—图灵机器人
  10. React 深度学习:React Core
  11. 前端一键复制粘贴插件——clipboard.js的使用
  12. 使用Cargo入门rust语言
  13. (转)iOS Wow体验 - 第六章 - 交互模型与创新的产品概念(1)
  14. win10下 你需要来自trustedinstaller的权限 修改权限
  15. 恩智浦(飞思卡尔)智能车舵机和电机PID控制
  16. kubernetes in action读书笔记(四)ConfigMap、Secret、滚动升级、downwardAPI、Deployment、Statefulset
  17. 现在最火爆的盲盒交友小程序源码
  18. 如何做机器学习模型质量保障及模型效果评测
  19. opengl随机地形生成
  20. 517coding网站P1960

热门文章

  1. html模拟终端,DomTerm:一款为Linux打造的终端模拟器
  2. 网络是怎样连接的学习笔记——从网线到网络设备
  3. 靖哥哥教你如何在docker中安装mysql
  4. 2021-2022启航出发
  5. 目标决定人生,制定属于你自己的目标
  6. Windows10蓝牙突然失灵 无法连接鼠标
  7. password unchanged Authentication token manipulation error
  8. Springboot启动后频繁打印错误日志 /null/swagger-ui.html解决方案
  9. 采购订单中带账户分配的总账科目确定(M和E的区别)
  10. LA 6657 GCD XOR