在上节中,我们把教程要求的3.1-3.3过了一遍,这一次回到正途上来。看看到底是怎么完成一个新的协议的。

本节中的代码实现了一些简单的“ping”协议(灵感来自“ns注释和文档”(现在更名为ns手册)的第9.6章中的“ping请求者”,但相当不同)。 一个节点将能够发送一个数据包到另一个节点,它将立即返回,以便可以计算往返时间。

1、头文件

在新的头文件'ping.h'中,首先必须声明将携带相关数据的新的Ping包头的数据结构。

struct hdr_ping {char ret;double send_time;
};

如果数据包正在从发送方正在被ping通的节点上,则char'ret'将被设置为“0”,而在返回路由时将被设置为“1”。 double “send_time”是发送时在分组上设置的时间戳,用于后来计算往返时间。

以下代码段将类“PingAgent”声明为类“Agent”的子类。

class PingAgent : public Agent {public:PingAgent();int command(int argc, const char*const* argv);void recv(Packet*, Handler*);protected:int off_ping_;
};

int off_ping_将用于访问数据包的ping头。 请注意,对于具有本地对象范围的变量通常使用尾随“_”。

在下面的部分中,将介绍定义构造函数“PingAgent()”的C ++代码以及在本声明中重新定义的函数'command()'和'recv()'。

2、c++代码

首先必须定义C ++代码和Tcl代码之间的联系。

首先,定义了协议头类以及应用类(C++中)


static class PingHeaderClass : public PacketHeaderClass {
public:PingHeaderClass() : PacketHeaderClass("PacketHeader/Ping", sizeof(hdr_ping)) {}
} class_pinghdr;static class PingClass : public TclClass {
public:PingClass() : TclClass("Agent/Ping") {}TclObject* create(int, const char*const*) {return (new PingAgent());}
} class_ping;

下一段代码是类“PingAgent”的构造函数。 它绑定了必须在Tcl和C ++中访问的变量。TCL中的(packetSize)——>C++(size)

PingAgent::PingAgent() : Agent(PT_PING)
{bind("packetSize_", &size_);bind("off_ping_", &off_ping_);
}

当执行类“PingAgent”的Tcl命令时,将调用函数'command()'。 在本案例中,将是'$ pa send'(假设'pa'是Agent / Ping类的一个实例),因为我们希望将ping数据包从代理发送到另一个ping代理。 我们基本上必须在'command()'函数中解析命令,如果没有匹配,则必须将其参数传递给基类的command()函数(在这种情况下为“代理” ::命令()'(详见代码倒数第二行的return))

int PingAgent::command(int argc, const char*const* argv)
{if (argc == 2) {if (strcmp(argv[1], "send") == 0) {// Create a new packetPacket* 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 packethdr->ret = 0;// Store the current time in the 'send_time' fieldhdr->send_time = Scheduler::instance().clock();// Send the packetsend(pkt, 0);// return TCL_OK, so the calling function knows that the// command has been processedreturn (TCL_OK);}}// If the command hasn't been processed by PingAgent()::command,// call the command() function for the base classreturn (Agent::command(argc, argv));
}

函数recv()定义了接收到数据包时要执行的操作。 如果'ret'字段为0,则必须返回“send_time”字段的值相同但“ret”字段设置为1的数据包。 如果'ret'为1,则会调用Tcl函数(必须由Tcl中的用户定义)函数并处理该事件。

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_timedouble stime = hdr->send_time;// Discard the packetPacket::free(pkt);// Create a new packetPacket* 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 echohdrret->ret = 1;                // Set the send_time field to the correct valuehdrret->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_.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);              }
}                                 

完整代码:

/** 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"static class PingHeaderClass : public PacketHeaderClass {
public:PingHeaderClass() : PacketHeaderClass("PacketHeader/Ping", sizeof(hdr_ping)) {}
} 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)
{bind("packetSize_", &size_);bind("off_ping_", &off_ping_);
}int PingAgent::command(int argc, const char*const* argv)
{if (argc == 2) {if (strcmp(argv[1], "send") == 0) {// Create a new packetPacket* 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 packethdr->ret = 0;// Store the current time in the 'send_time' fieldhdr->send_time = Scheduler::instance().clock();// Send the packetsend(pkt, 0);// return TCL_OK, so the calling function knows that the// command has been processedreturn (TCL_OK);}}// If the command hasn't been processed by PingAgent()::command,// call the command() function for the base classreturn (Agent::command(argc, argv));
}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_timedouble stime = hdr->send_time;// Discard the packetPacket::free(pkt);// Create a new packetPacket* 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 echohdrret->ret = 1;// Set the send_time field to the correct valuehdrret->send_time = stime;// Send the packetsend(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 timesprintf(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 packetPacket::free(pkt);}
}

NS2相关学习——完成一个新协议(2)相关推荐

  1. NS2相关学习——完成一个新协议(3)

    在前面已经基本学习了怎么完成一个新协议(一个神奇的ping协议,然鹅还是有点懵...) 接下来继续学习相关知识 接着上一部分从1开始 1.必要的修改 如果想要添加添加新的代理程序,就需要修改NS源文件 ...

  2. NS2相关学习——完成一个新的协议(1)

    接下来要进入对我来说老大难的环节了,从表面的TCL慢慢进入到后端的C++,一起加油学习吧~ 在本节学习中,将给出一个在ns中实现新的协议的例子.但是可以想见的是,如果由我们自己来完成这个工作,势必要对 ...

  3. NS2相关学习——可靠的MANET应用程序的Gossip协议分析

    好久不写,应该努力啦!老师把这篇论文给了我,现在还不知道它在讲什么,来边翻译边学习吧! 文章链接:https://www.researchgate.net/publication/316844643_ ...

  4. NS2相关学习——在ns中模拟无线场景

    之前学习的都是有线场景下的NS2相关应用,现在开始,终于要学习无线啦!无线是我研究的重点,要好好学习呀! 在本节中,我们将学习使用ns中提供的移动无线仿真模型. 该部分由两部分组成. 在第一小节中,我 ...

  5. 语义表征的无监督对比学习:一个新理论框架

    点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」7折优惠最后3天,请扫码咨询 ↑↑↑ 译者 | Linstancy 责编 | 琥珀 出品 | AI科技大本营(ID:rgznai100) ...

  6. NS2相关学习——创建Xgraph的输出文件

    经过前面学习代码的编写,这一部分,我们要学会如何进行分析,一个很直观的方式就是将结果图形化表示出来. ns-allinone包的一部分是"xgraph",一个绘图程序,可用于创建模 ...

  7. ns2相关学习——TCL脚本编写(3)

    在这里我们将学习动态网络的建立 1.建立拓扑 当节点很多的时候,我们可以使用循环的方式来建立拓扑. for {set i 0} {$i < 7} {incr i} {set n($i) [$ns ...

  8. ns2相关学习——TCL脚本编写(2)

    下面来学习更加复杂一点的TCL脚本的编写 简述:建立有4个节点的拓扑,其中一个节点作为路由器,用来将两个节点发出的数据包转发到第四个节点上面. 在这里将解释将两个节点的数据流区分开来的方法,展示如何去 ...

  9. 蓝牙相关学习:3.BLE协议物理层

    物理层 频段 调制 信道 跳频 参考地址 Physical Layer 简称 PHY(物理层) 由于BLE属于无线通信,则其通信介质是一定频率范围下的频带资源(Frequency Band) 频段 B ...

最新文章

  1. 星型模型和雪花型模型比较
  2. 函数学习-delattr()
  3. java6集合编程题
  4. Azure App Service 健康检查正式发布
  5. 数据结构一【树状数组】普通、二维、离线树状数组的(单点修改,单点查询,区间修改,区间查询)模板及应用例题总结
  6. java 中negate()_Java BigInteger negate()用法及代码示例
  7. SinoBBD跨入大数据产业发展新模式
  8. html页面图片翻转特效代码,如何使用css实现翻转图片的效果(附代码)
  9. python查找手册
  10. Endnote 自定义参考文献样式
  11. Java--数组和集合之间的相互转换
  12. // #ifdef MP-WEIXIN微信小程序无效,不执行
  13. jsp实验中:tag文件报java.util.ArrayList cannot be cast to java.lang.String
  14. 【codeforces85D】
  15. 十六宫格拼图(A*/IDA*)(曼哈顿距离)
  16. 【数字图像处理】空间滤波
  17. 啊,CET6 2021年
  18. 第一章:计算机硬件知识
  19. prototype全解全析
  20. 央视315晚会 惠普“雪花屏”门被搬出 垃圾惠普

热门文章

  1. 安装openCV到VS2010,Win764位机时遇到的问题的解决办法
  2. JAVA入门级教学之(算数运算符)
  3. @mapperscan注解_Spring的@Import注解详解
  4. python次方运算_neg__python 魔术方法1 运算符重载
  5. python给字母赋值_给字母赋值的更快方法?
  6. python的加减乘除运算_python实现四则运算
  7. c4d启动无反应_浙江无填料喷雾式冷却塔
  8. python识别人脸多种属性_深度学习人脸识别仅9行python代码实现?同时高效处理100张相片?...
  9. 基于java二手书论文_java毕业设计_springboot框架的二手书交易管理与实现
  10. python qt开发_Python 使用Qt进行开发(三)