tictoc 6-9
- tictoc 6 自消息实现计时
- tictoc 7 节点等待时延随机,丢失包概率
- tictoc 8 两个节点分别定义两个类
- tictoc 9 保留原始包副本,从而不需要重新构建包
tictoc 6 自消息实现计时
- 在前面的模型中,’ tic’和’ toc’立即将收到的消息发送回。这里将添加一些计时:tic和toc将在将消息发送回之前模拟地保持消息1秒。
在omnet++中,这种计时是通过模块向自身发送消息来实现的。
这样的消息称为自消息(但仅仅是因为它们的使用方式,否则它们就是完全普通的消息)或事件。 - 可以使用
scheduleAt()
函数“发送”自消息,并且您可以指定它们应该在何时返回模块。 - 我们不会立即开始,而是向自己发送一条信息(“自我信息”)——当它返回给我们时,我们会在模拟时间t=5.0时进行第一次发送。(
tictocMsg = new cMessage("tictocMsg"); scheduleAt(5.0, event);
) - 自我消息到达了,所以我们可以发送tictocMsg和nullptr它的指针,这样以后就不会让我们感到困惑了。(
send(tictocMsg, "out"); tictocMsg = nullptr;
) - 如果我们收到的信息不是我们的自我信息,那么它一定是我们的伴侣发来的信息。我们记住它在
tictocMsg
变量中的指针,然后安排我们的自消息在模拟的1s时间内返回给我们。(scheduleAt(simTime()+1.0, event);
)
ned文件(还是两个结点不变)
simple Txc6
{
parameters:
@display("i=block/routing");
gates:
input in;
output out;
}
network Tictoc6
{
submodules:
tic: Txc6 {
parameters:
@display("i=,cyan");
}
toc: Txc6 {
parameters:
@display("i=,gold");
}
connections:
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
}
cc文件
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* In the previous models, `tic' and `toc' immediately sent back the
* received message. Here we'll add some timing: tic and toc will hold the
* message for 1 simulated second before sending it back. In OMNeT++
* such timing is achieved by the module sending a message to itself.
* Such messages are called self-messages (but only because of the way they
* are used, otherwise they are completely ordinary messages) or events.
* Self-messages can be "sent" with the scheduleAt() function, and you can
* specify when they should arrive back at the module.
*
* We leave out the counter, to keep the source code small.
* 在前面的模型中,' tic'和' toc'立即将收到的消息发送回。这里我们将添加一些计时:tic和toc将在将消息发送回之前模拟地保持消息1秒。在omnet++中,这种计时是通过模块向自身发送消息来实现的。这样的消息称为自消息(但仅仅是因为它们的使用方式,否则它们就是完全普通的消息)或事件。可以使用scheduleAt()函数“发送”自消息,并且您可以指定它们应该在何时返回模块。
*/
class Txc6 : public cSimpleModule
{
private:
cMessage *event; // pointer to the event object which we'll use for timing,指向我们将用于计时的事件对象的指针
cMessage *tictocMsg; // variable to remember the message until we send it back,变量来记住消息,直到我们将其发送回
public:
Txc6();
virtual ~Txc6();
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Txc6);
Txc6::Txc6()
{
// Set the pointer to nullptr, so that the destructor won't crash
// even if initialize() doesn't get called because of a runtime
// error or user cancellation during the startup process.
//将指针设置为nullptr,这样即使在启动过程中由于运行时错误或用户取消而没有调用initialize(),析构函数也不会崩溃。
event = tictocMsg = nullptr;
}
Txc6::~Txc6()
{
// Dispose of dynamically allocated the objects,处理动态分配的对象
cancelAndDelete(event);
delete tictocMsg;
}
void Txc6::initialize()
{
// Create the event object we'll use for timing -- just any ordinary message.创建用于计时的事件对象——任何普通消息。
event = new cMessage("event");
// No tictoc message yet.
tictocMsg = nullptr;
if (strcmp("tic", getName()) == 0) {
// We don't start right away, but instead send an message to ourselves
// (a "self-message") -- we'll do the first sending when it arrives
// back to us, at t=5.0s simulated time.我们不会立即开始,而是向自己发送一条信息(“自我信息”)——当它返回给我们时,我们会在模拟时间t=5.0时进行第一次发送。
EV << "Scheduling first send to t=5.0s\n";
tictocMsg = new cMessage("tictocMsg");
scheduleAt(5.0, event);
}
}
void Txc6::handleMessage(cMessage *msg)
{
// There are several ways of distinguishing messages, for example by message
// kind (an int attribute of cMessage) or by class using dynamic_cast
// (provided you subclass from cMessage). In this code we just check if we
// recognize the pointer, which (if feasible) is the easiest and fastest
// method.
//有几种方法来区分消息,例如通过消息类型(cMessage的int属性)或通过使用dynamic_cast的类(提供来自cMessage的子类)。在这段代码中,我们只是检查是否识别了指针,这(如果可行)是最简单和最快的方法。
if (msg == event) {
// The self-message arrived, so we can send out tictocMsg and nullptr out
// its pointer so that it doesn't confuse us later. 自我消息到达了,所以我们可以发送tictocMsg和nullptr它的指针,这样以后就不会让我们感到困惑了。
EV << "Wait period is over, sending back message\n";
send(tictocMsg, "out");
tictocMsg = nullptr;
}
else {
// If the message we received is not our self-message, then it must
// be the tic-toc message arriving from our partner. We remember its
// pointer in the tictocMsg variable, then schedule our self-message
// to come back to us in 1s simulated time.如果我们收到的信息不是我们的自我信息,那么它一定是我们的伴侣发来的一字合一的信息。我们记住它在tictocMsg变量中的指针,然后安排我们的自消息在模拟的1s时间内返回给我们。
EV << "Message arrived, starting to wait 1 sec...\n";
tictocMsg = msg;
scheduleAt(simTime()+1.0, event);
}
}
tictoc 7 节点等待时延随机,丢失包概率
- 这一步我们引入随机数。我们将延迟从1更改为一个可以从NED文件或omnetpp.ini中设置的随机值。此外,我们会以很小的概率“丢失”(删除)数据包。
- ini初始化中在等待自消息结束后,其中一个节点开始向对方发送消息
- 处理消息时候,如果是自消息事件,则继续发送消息出去。否则会有个丢失概率为0.1 的判断
if (uniform(0, 1) < 0.1)
,可能会丢失消息 - “
delayTime
"模块参数可以设置为"exponential(5)
”(tictoc7。Ned, omnetpp.ini),然后在这里我们每次都会得到不同的延迟。
ini配置
[Config Tictoc7]
network = Tictoc7
# argument to exponential() is the mean; truncnormal() returns values from
#指数()的参数是平均值;Truncnormal()返回来自的值
# the normal distribution truncated to nonnegative values
#正态分布截断为非负值
Tictoc7.tic.delayTime = exponential(3s)
Tictoc7.toc.delayTime = truncnormal(3s,1s)
ned文件
simple Txc7
{
parameters:
volatile double delayTime @unit(s); // delay before sending back message,发送回消息前的延迟
@display("i=block/routing");
gates:
input in;
output out;
}
network Tictoc7
{
submodules:
tic: Txc7 {
parameters:
@display("i=,cyan");
}
toc: Txc7 {
parameters:
@display("i=,gold");
}
connections:
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
}
cc文件
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* In this step we'll introduce random numbers. We change the delay from 1s
* to a random value which can be set from the NED file or from omnetpp.ini.
* In addition, we'll "lose" (delete) the packet with a small probability.
* 这一步我们引入随机数。我们将延迟从1更改为一个可以从NED文件或omnetpp.ini中设置的随机值。此外,我们会以很小的概率“丢失”(删除)数据包。
*/
class Txc7 : public cSimpleModule
{
private:
cMessage *event;
cMessage *tictocMsg;
public:
Txc7();
virtual ~Txc7();
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Txc7);
Txc7::Txc7()
{
event = tictocMsg = nullptr;
}
Txc7::~Txc7()
{
cancelAndDelete(event);
delete tictocMsg;
}
void Txc7::initialize()
{
event = new cMessage("event");
tictocMsg = nullptr;
if (strcmp("tic", getName()) == 0) {
EV << "Scheduling first send to t=5.0s\n";
scheduleAt(5.0, event);
tictocMsg = new cMessage("tictocMsg");
}
}
void Txc7::handleMessage(cMessage *msg)
{
if (msg == event) {
EV << "Wait period is over, sending back message\n";
send(tictocMsg, "out");
tictocMsg = nullptr;
}
else {
// "Lose" the message with 0.1 probability:“丢失”信息的概率为0.1:
if (uniform(0, 1) < 0.1) {
EV << "\"Losing\" message\n";
delete msg;
}
else {
// The "delayTime" module parameter can be set to values like
// "exponential(5)" (tictoc7.ned, omnetpp.ini), and then here
// we'll get a different delay every time.
//"delayTime"模块参数可以设置为"指数(5)"(tictoc7。Ned, omnetpp.ini),然后在这里我们每次都会得到不同的延迟。
simtime_t delay = par("delayTime");
EV << "Message arrived, starting to wait " << delay << " secs...\n";
tictocMsg = msg;
scheduleAt(simTime()+delay, event);
}
}
}
tictoc 8 两个节点分别定义两个类
- 让我们退一步,从代码中去除随机延迟。然而,我们会离开,以很小的可能性失去这个包。我们会做一些在电信网络中很常见的事情:如果数据包在一定时间内没有到达,我们就会假设它丢失了,并创建另一个。超时将使用(还有什么?)一条自消息来处理。
ned文件,tic 和toc 分开各自定义
simple Tic8
{
parameters:
@display("i=block/routing");
gates:
input in;
output out;
}
simple Toc8
{
parameters:
@display("i=block/process");
gates:
input in;
output out;
}
network Tictoc8
{
submodules:
tic: Tic8 {
parameters:
@display("i=,cyan");
}
toc: Toc8 {
parameters:
@display("i=,gold");
}
connections:
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
}
cc文件
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* Let us take a step back, and remove random delaying from the code.
* We'll leave in, however, losing the packet with a small probability.
* And, we'll we do something very common in telecommunication networks:
* if the packet doesn't arrive within a certain period, we'll assume it
* was lost and create another one. The timeout will be handled using
* (what else?) a self-message.
* 让我们退一步,从代码中去除随机延迟。然而,我们会离开,以很小的可能性失去这个包。我们会做一些在电信网络中很常见的事情:如果数据包在一定时间内没有到达,我们就会假设它丢失了,并创建另一个。超时将使用(还有什么?)一条自消息来处理。
*/
class Tic8 : public cSimpleModule
{
private:
simtime_t timeout; // timeout
cMessage *timeoutEvent; // holds pointer to the timeout self-message 保持指向超时自消息的指针
public:
Tic8();
virtual ~Tic8();
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Tic8);
Tic8::Tic8()
{
timeoutEvent = nullptr;
}
Tic8::~Tic8()
{
cancelAndDelete(timeoutEvent);
}
void Tic8::initialize()
{
// Initialize variables.
timeout = 1.0;
timeoutEvent = new cMessage("timeoutEvent");
// Generate and send initial message.
EV << "Sending initial message\n";
cMessage *msg = new cMessage("tictocMsg");
send(msg, "out");
scheduleAt(simTime()+timeout, timeoutEvent);
}
void Tic8::handleMessage(cMessage *msg)
{
if (msg == timeoutEvent) {
// If we receive the timeout event, that means the packet hasn't
// arrived in time and we have to re-send it.
EV << "Timeout expired, resending message and restarting timer\n";
cMessage *newMsg = new cMessage("tictocMsg");
send(newMsg, "out");
scheduleAt(simTime()+timeout, timeoutEvent);
}
else { // message arrived
// Acknowledgement received -- delete the received message and cancel
// the timeout event.
EV << "Timer cancelled.\n";
cancelEvent(timeoutEvent);
delete msg;
// Ready to send another one.
cMessage *newMsg = new cMessage("tictocMsg");
send(newMsg, "out");
scheduleAt(simTime()+timeout, timeoutEvent);
}
}
/**
* Sends back an acknowledgement -- or not.
*/
class Toc8 : public cSimpleModule
{
protected:
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Toc8);
void Toc8::handleMessage(cMessage *msg)
{
if (uniform(0, 1) < 0.1) {
EV << "\"Losing\" message.\n";
bubble("message lost"); // making animation more informative...使动画更加翔实..
delete msg;
}
else {
EV << "Sending back same message as acknowledgement.\n";
send(msg, "out");
}
}
tictoc 9 保留原始包副本,从而不需要重新构建包
- 在前面的模型中,如果需要重传,我们只创建另一个包。这是可以的,因为包包含的内容并不多,但在现实生活中,通常更实际的做法是保留原始包的副本,这样我们就可以重新发送它,而不需要重新构建它。
- 复制包:
void Tic9::sendCopyOf(cMessage *msg)
{
// Duplicate message and send the copy.
cMessage *copy = (cMessage *)msg->dup();
send(copy, "out");
}
创建并返回此对象的精确副本,但消息ID除外(克隆被分配了一个新ID)。注意,消息的创建时间也会被复制,因此相同消息对象的克隆具有相同的创建时间。参见cObject了解更多细节。
/**
* Creates and returns an exact copy of this object, except for the
* message ID (the clone is assigned a new ID). Note that the message
* creation time is also copied, so clones of the same message object
* have the same creation time. See cObject for more details.
* 创建并返回此对象的精确副本,但消息ID除外(克隆被分配了一个新ID)。
* 注意,消息的创建时间也会被复制,因此相同消息对象的克隆具有相同的创建时间。
* 参见cObject了解更多细节。
*/
virtual cMessage *dup() const override {return new cMessage(*this);}
ned文件
simple Tic9
{
parameters:
@display("i=block/routing");
gates:
input in;
output out;
}
simple Toc9
{
parameters:
@display("i=block/process");
gates:
input in;
output out;
}
//
// Same as Tictoc8.
//
network Tictoc9
{
submodules:
tic: Tic9 {
parameters:
@display("i=,cyan");
}
toc: Toc9 {
parameters:
@display("i=,gold");
}
connections:
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
}
cc文件
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* In the previous model we just created another packet if we needed to
* retransmit. This is OK because the packet didn't contain much, but
* in real life it's usually more practical to keep a copy of the original
* packet so that we can re-send it without the need to build it again.
* 在前面的模型中,如果需要重传,我们只创建另一个包。这是可以的,因为包包含的内容并不多,但在现实生活中,通常更实际的做法是保留原始包的副本,这样我们就可以重新发送它,而不需要重新构建它。
*/
class Tic9 : public cSimpleModule
{
private:
simtime_t timeout; // timeout
cMessage *timeoutEvent; // holds pointer to the timeout self-message
int seq; // message sequence number
cMessage *message; // message that has to be re-sent on timeout
public:
Tic9();
virtual ~Tic9();
protected:
virtual cMessage *generateNewMessage();
virtual void sendCopyOf(cMessage *msg);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Tic9);
Tic9::Tic9()
{
timeoutEvent = message = nullptr;
}
Tic9::~Tic9()
{
cancelAndDelete(timeoutEvent);
delete message;
}
void Tic9::initialize()
{
// Initialize variables.
seq = 0;
timeout = 1.0;
timeoutEvent = new cMessage("timeoutEvent");
// Generate and send initial message.
EV << "Sending initial message\n";
message = generateNewMessage();
sendCopyOf(message);//拷贝并发送
scheduleAt(simTime()+timeout, timeoutEvent);
}
void Tic9::handleMessage(cMessage *msg)
{
if (msg == timeoutEvent) {
// If we receive the timeout event, that means the packet hasn't
// arrived in time and we have to re-send it.
EV << "Timeout expired, resending message and restarting timer\n";
sendCopyOf(message);
scheduleAt(simTime()+timeout, timeoutEvent);
}
else { // message arrived
// Acknowledgement received!
EV << "Received: " << msg->getName() << "\n";
delete msg;
// Also delete the stored message and cancel the timeout event.
EV << "Timer cancelled.\n";
cancelEvent(timeoutEvent);
delete message;
// Ready to send another one.
message = generateNewMessage();
sendCopyOf(message);
scheduleAt(simTime()+timeout, timeoutEvent);
}
}
cMessage *Tic9::generateNewMessage()
{
// Generate a message with a different name every time.
char msgname[20];
sprintf(msgname, "tic-%d", ++seq);
cMessage *msg = new cMessage(msgname);
return msg;
}
void Tic9::sendCopyOf(cMessage *msg)
{
// Duplicate message and send the copy.
cMessage *copy = (cMessage *)msg->dup();
send(copy, "out");
}
/**
* Sends back an acknowledgement -- or not.
*/
class Toc9 : public cSimpleModule
{
protected:
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Toc9);
void Toc9::handleMessage(cMessage *msg)
{
if (uniform(0, 1) < 0.1) {
EV << "\"Losing\" message " << msg << endl;
bubble("message lost");
delete msg;
}
else {
EV << msg << " received, sending back an acknowledgement.\n";
delete msg;
send(new cMessage("ack"), "out");
}
}