本文初衷
当我发现我必须要做NS3网络仿真的时候,我内心是拒绝的,一方面NS3完全没接触过,另一方面,C++语言接触也不是太多,感觉工作量好大。但是,真的是不做不行了。然后,我就到网上查一些关于NS3的仿真内容,入门什么的,感觉真的是好混乱啊,这个东西没有一个明确的教程,都是一些杂乱的CSDN和技术博客,看起来十分混乱,而且有些现成的代码都是好多好多年前的,让人很难受。所以,我就写了本文,希望能对你有所帮助,静下心来从头往后看吧。
第一步 linux系统的使用
既然你已经准备好进行NS3仿真了,那么就先静下心来安装一个NS3吧,但是NS3都是运行在linux系统下的,所以,你先要安装一个linux系统。linux系统你可以直接安装到电脑上,当然你也可以使用linux虚拟机进行安装(我是在虚拟机上安装的),推荐的虚拟软件是VMware,这个软件可以创建一个虚拟机,就是可以创建一个虚拟的linux系统,这样你就可以不影响自己windows系统的情况下,轻松的使用NS3了,你可以百度一下VMware安装教程,也可以使用我下面的百度云链接进行下载安装。VMware的使用在这里就不赘述了,安装和使用还是比较容易的。
链接:https://pan.baidu.com/s/1vKbVrIKDqueMdywsYFzZqA
提取码:crv1
第二步 NS3的安装
NS3的安装在网上有很多教程,可自行查找,我使用的版本是3.25
第三步 了解一下NS3开发流程
选择或开发相应模块:根据实际仿真对象和仿真场景选择相应的仿真模块:如果是有线局域网络(CSMA)还是无线局域网络(Wi-Fi);节点是否需要移动(mobility);使用何种应用程序(application);是否需要能量(energy)管理;使用何种路由协议(internet、aodv等);是否需要动画演示等可视化界面(visualizer、netanim)等。如果要搭建的网络是比较新的网络,如延迟容忍网络(DTN)等,需要开发设计协议,如路由协议、移动模型、能量管理模型等。
编写网络仿真脚本:有了相应的模块,就可以搭建网络仿真环境,ns3仿真脚本支持两种语言:C++和Python,但是两种语言的API接口是一样的,部分API可能还没有提供Python接口。编写ns3仿真脚本的大体过程如下。
其中节点,网络设备,信道,应用程序的基本概念可以参照下面的这个文章
https://blog.csdn.net/weichanghu_/article/details/83306998
第四步 了解一下NS3的时间调度机制
https://blog.csdn.net/rustfree/article/details/84558058
第五步 NS3官网给了first.cc点对点,CSMA和wifi 的示例
通过这个示例你就可以了解大概的一个开发流程了
https://www.docin.com/p-2009136480.html
第六步 NS3 API
这个时候NS3的大概框架应该掌握的差不多了,那么就可以试着看下面的代码了,然后这个文档里会定义一些NS3的一些特殊类,可以到这里查找,以及一些模型,也可以在这里查找,值得注意是,这个API有些古老,有些特性已经变了,比如随机指数变量的使用。
https://www.nsnam.org/docs/release/3.7/doxygen/annotated.html
第七步 80215.7CSMA/CA的代码(仅供学习参考,不可全信,可能会有错误没有发现)
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//头文件包含,在h文件中进行函数声明,在cpp文件中完成函数的实现
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
//定义命名空间
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("MacCsma");
class VLCNode;
class VLCChannel{
public:
//这应该是一个类的初始化函数
VLCChannel(){
state=2;
ChannelSendTimeStamp=0;
ChannelCcaTimeStamp=0;
// AllPacketDelayPosition=0;
collisionTimes=0;
SumOfSuccessSendPackets=0;
AllPacketDelayVector.clear();
}
int state; //1-busy,2-free,3-sleep
uint64_t ChannelSendTimeStamp;
uint64_t ChannelCcaTimeStamp;
uint64_t everySlotStartTimeStamp[16];
uint64_t collisionTimes;
EventId NextEndTxEventId; //信道记录下一个结束发送事件ID,用于取消碰撞时先发送的数据包
int TheNodeIdOfNextEndTxEventId; //下一个结束发送事件的节点ID号,用于告知已经发送的节点产生碰撞
VLCNode *nodes[20]; //数组下标为节点ID号
void SetBusy()
{
state=1;
}
void SetFree()
{
state=2;
}
// uint64_t AllPacketDelay[100000]; //统计所有数据包延时
// int AllPacketDelayPosition; //插入延时信息位置
uint64_t SumOfSuccessSendPackets; //所有成功传输的数据量之和
std::vector<uint64_t> AllPacketDelayVector;
};
class VLCNode{
public:
VLCNode(){
opticalClockDuration=5000;
macMaxBE=5;
macMinBE=3;
NB=0;
BE=macMinBE;
macMaxRABackoffs=4; //最大退避次数
oneBackoffTime=20*opticalClockDuration; //the time of one backoff
rate=1000000; //数据发送速率,对照协议MCSID取值不同设置
ackWaitDuration=20+240+103; // PHY II 是20+5120+103=5243;PHY III 是20+5120+111=5251
// macMaxFrameTotalWaitTime=10000000; //不用
wasSuspend=false;
RandomAccessing=false;
NodeId=0;
numsOfCollision=0;
NumOfLostPackets=0;
NumsOfCCA=0;
NumsOfCCABusy=0;
NumsOfSendToChannel=0;
}
uint64_t NextSlotStartInterval(uint64_t timeStamp)
{
uint64_t result=0;
for(int i=0;i<16;i++)
{
if(timeStamp<(channel->everySlotStartTimeStamp[i]))
{
result=channel->everySlotStartTimeStamp[i]-timeStamp;
break;
}
else
{
}
}
return result;
}
void PacketCome(int packetSize)
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
if(channel->state==3)
{
//如果包来到的时候信道是不活跃状态,那么不进行随机接入函数调用,就先把包存到队列里就好了
packetSizeList.push_back(packetSize);
packetComeTimeStampList.push_back(Simulator::Now().GetNanoSeconds());
}
else
{
packetSizeList.push_back(packetSize);
packetComeTimeStampList.push_back(Simulator::Now().GetNanoSeconds());
if(!RandomAccessing)
//如果当前节点没有正在进行随机接入则开始,如果已经有随机接入,则等待随机接入完成再进行
{
startRandomAccess();
}
}
}
void startRandomAccess()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
RandomAccessing=true;
if(!packetSizeList.empty()) //packet list is not empty
{
NB=0;
BE=macMinBE;
uint64_t afterBeaconTime=0; //距离本次超帧中的信标帧时长
afterBeaconTime=Simulator::Now().GetNanoSeconds()-channel->everySlotStartTimeStamp[0];
uint64_t remainTime=afterBeaconTime%((uint64_t)20*opticalClockDuration); //remainTime是第一次时间对齐需要的时间,加上退避时间即第一次CCA需要继续等待的时间
Simulator::Schedule(NanoSeconds(remainTime),&VLCNode::firstBackoff,this);
}
else //packet list is empty
{
//当包没有到来的时候,是什么也不执行的,等待packcome()函数再次调用
}
}
void firstBackoff()
{
NS_LOG_FUNCTION(this<<"NodeId is:"<<NodeId);
//计算一下退避的时间,并在此时间后执行CCA过程
uint64_t backoffs=rand()%((int)pow(2,BE)-1);
uint64_t backoffTime=backoffs*oneBackoffTime;
CCABusyTimeStamp=Simulator::Now().GetNanoSeconds();
Simulator::Schedule(NanoSeconds(backoffTime),&VLCNode::CCA,this);
}
void CCA()
{
backoffTime=0;
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId<<"channelState"<<channel->state);
uint64_t CcaInterval=Simulator::Now().GetNanoSeconds()-channel->ChannelCcaTimeStamp;
NumsOfCCA++; //统计节点进行CCA总次数
if(CcaInterval<1000) //CCA 时间间隔小于1000ns,认为碰撞发生
{
NumsOfSendToChannel++;
collision();
}
else //未发生碰撞正常执行CCA
{
NodeCcaTimeStamp=Simulator::Now().GetNanoSeconds();
channel->ChannelCcaTimeStamp=NodeCcaTimeStamp;
if(channel->state==1) //channel is busy: nums of backoff ++
{
NB++;
BE++;
NumsOfCCABusy++; //统计检测信道忙总次数
if(BE>macMaxBE)
{
BE=macMaxBE;
}
else
{
}
// NS_LOG_DEBUG("the NB is :"<<NB<<"the macMaxRABackoffs is"<<macMaxRABackoffs);
if(NB>=macMaxRABackoffs)
{
failure(); //failure
}
else
{
CCABusyTimeStamp=Simulator::Now().GetNanoSeconds();
// uint64_t remainSlotTime=NextSlotStartInterval(Simulator::Now().GetNanoSeconds()); //确定距离下一个时隙时间差
uint64_t backoffs=rand()%((int)pow(2,BE)-1);
backoffTime=backoffs*oneBackoffTime;
CCAEvent=Simulator::Schedule(NanoSeconds(backoffTime),&VLCNode::CCA,this);
}
}
else if(channel->state==2) //channel is free : send
{
NumsOfSendToChannel++;
//recieve ack time
uint64_t getAckTime=(rand()%ackWaitDuration+400)*opticalClockDuration; //接收到ACK的时间,400是长帧间间隔
ACKAndIFSDuration=getAckTime;
uint64_t thePacketSizeWithHeader=packetSizeList.front()+4+8;
double onlyDataDuration=(double)thePacketSizeWithHeader*8*1000000000/(double)rate;
// NS_LOG_DEBUG("onlyDataDuration is:"<<onlyDataDuration);
// NS_LOG_DEBUG("getAckTime is:"<<getAckTime);
uint64_t txDuration=onlyDataDuration+getAckTime;
NodeSendTimeStamp=Simulator::Now().GetNanoSeconds();//节点开始发送时间戳
channel->ChannelSendTimeStamp=NodeSendTimeStamp;//信道开始发送时间戳
EndTxEvent=Simulator::Schedule(NanoSeconds(txDuration),&VLCNode::endTx,this);
channel->TheNodeIdOfNextEndTxEventId=NodeId;
channel->NextEndTxEventId=EndTxEvent;
channel->state=1; //set channel is busy
}
}
}
void endTx()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
RandomAccessing=false;
if(channel->state==1) //信道状态等于发送时设置的忙
{
if(NodeSendTimeStamp!=channel->ChannelSendTimeStamp)
{
collision();
}
else
{
channel->state=2;
if(!packetComeTimeStampList.empty())
{
uint64_t delay=Simulator::Now().GetNanoSeconds()-packetComeTimeStampList.front();
// NS_LOG_INFO("the delay with ack and LIFS is :"<<delay);
// NS_LOG_INFO("the delay without ack and LIFS is :"<<delay-ACKAndIFSDuration);
// channel->AllPacketDelay[channel->AllPacketDelayPosition]=delay-ACKAndIFSDuration;
// channel->AllPacketDelayPosition++;
channel->AllPacketDelayVector.push_back(delay-ACKAndIFSDuration);
}
if(!packetSizeList.empty())
{
uint64_t PacketSize=packetSizeList.front();//统计所有成功发送数据包
channel->SumOfSuccessSendPackets=channel->SumOfSuccessSendPackets+PacketSize;
packetSizeList.pop_front();
packetComeTimeStampList.pop_front();
}
else
{
}
if(!packetSizeList.empty())
{
startRandomAccess();
}
}
}
else if(channel->state==2) //信道状态被其他节点修改为空闲,发生碰撞
{
collision();
}
else //信道由超帧设置为休眠
{
}
}
void isNotifiedCollision()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
// numsOfCollision++;
channel->collisionTimes++; //信道中记录所有节点碰撞次数
NB++;
BE++;
if(BE>macMaxBE)
{
BE=macMaxBE;
}
else
{
}
// NS_LOG_DEBUG("the NB is :"<<NB<<"the macMaxRABackoffs is"<<macMaxRABackoffs);
if(NB>=macMaxRABackoffs)
{
failure(); //failure
}
else
{
// CCABusyTimeStamp=Simulator::Now().GetNanoSeconds();
uint64_t thePacketSizeWithHeader=packetSizeList.front()+4+8;
double onlyDataDuration=(double)thePacketSizeWithHeader*8*1000000000/(double)rate;
uint64_t sendDuration=onlyDataDuration+ackWaitDuration;
Simulator::Schedule(NanoSeconds(sendDuration),&VLCChannel::SetFree,channel); //被告知碰撞,在预期的接收ACK时间到达后将信道设置为空闲
// uint64_t remainSlotTime=NextSlotStartInterval(Simulator::Now().GetNanoSeconds()+sendDuration);
uint64_t backoffs=rand()%((int)pow(2,BE)-1);
backoffTime=backoffs*oneBackoffTime;
CCAEvent=Simulator::Schedule(NanoSeconds(sendDuration+backoffTime),&VLCNode::CCA,this);
}
}
void collision()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
// NS_LOG_INFO("collison");
// EndTxEvent.Cancel();
channel->NextEndTxEventId.Cancel();
// NS_LOG_DEBUG("the channel->TheNodeIdOfNextEndTxEventId:"<<channel->TheNodeIdOfNextEndTxEventId);
channel->nodes[channel->TheNodeIdOfNextEndTxEventId]->isNotifiedCollision();
// channel->nodes[channel->TheNodeIdOfNextEndTxEventId]->collision();
// channel->AllPacketDelayPosition--;
// channel->AllPacketDelayVector.pop_back();
numsOfCollision++;
NB++;
BE++;
if(BE>macMaxBE)
{
BE=macMaxBE;
}
else
{
}
// NS_LOG_DEBUG("the NB is :"<<NB<<"the macMaxRABackoffs is"<<macMaxRABackoffs);
if(NB>=macMaxRABackoffs)
{
failure(); //failure
}
else
{
CCABusyTimeStamp=Simulator::Now().GetNanoSeconds();
uint64_t thePacketSizeWithHeader=packetSizeList.front()+4+8;
double onlyDataDuration=(double)thePacketSizeWithHeader*8*1000000000/(double)rate;
uint64_t sendDuration=onlyDataDuration+ackWaitDuration;
Simulator::Schedule(NanoSeconds(sendDuration),&VLCChannel::SetFree,channel); //碰撞发生后,在预期的接收ACK时间到达后将信道设置为空闲
// uint64_t remainSlotTime=NextSlotStartInterval(Simulator::Now().GetNanoSeconds()+sendDuration);
uint64_t backoffs=rand()%((int)pow(2,BE)-1);
backoffTime=backoffs*oneBackoffTime;
CCAEvent=Simulator::Schedule(NanoSeconds(backoffTime),&VLCNode::CCA,this);
}
}
void failure()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
// NS_LOG_INFO("one packet failure,NodeId"<<NodeId);
NumOfLostPackets++;
RandomAccessing=false;
if(!packetSizeList.empty())
{
packetSizeList.pop_front();
packetComeTimeStampList.pop_front();
}
else
{
}
if(!packetSizeList.empty())
{
startRandomAccess();
}
}
void suspend()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
CCAEvent.Cancel();
wasSuspend=true;
CAPRestartAccessBackofftime=Simulator::Now().GetNanoSeconds()-CCABusyTimeStamp;
}
void CAPRestartAccess()
{
NS_LOG_FUNCTION(this<<"NodeId"<<NodeId);
if(wasSuspend)
//如果之前被中断,则根据剩余退避时间退避,也就是重新恢复之前的接入过程
{
wasSuspend=false;
Simulator::Schedule(NanoSeconds(CAPRestartAccessBackofftime),&VLCNode::CCA,this);
}
else //如果之前没有被中断,则看数据队列是否为空,非空则发起随机接入算法
{
if(!packetSizeList.empty())
{
startRandomAccess();
}
}
}
int NB;
int BE;
int macMaxBE;
int macMinBE;
int macMaxRABackoffs;
int oneBackoffTime; //the time of one backoff
// int macMaxFrameTotalWaitTime;
uint64_t CCABusyTimeStamp;
uint64_t backoffTime; //退比时长
EventId CCAEvent;
EventId EndTxEvent;
uint64_t CAPRestartAccessBackofftime; //下一个超帧开始,随机介入重启需要退避时间
bool wasSuspend; //是否因为超帧结束导致CCA延迟,true是,false否
int NumOfLostPackets; //超过最大退避次数,失败
bool RandomAccessing; //true-正在进行随机接入过程,进入休眠需要suspend
int NodeId;
int numsOfCollision;
int NumsOfCCA;
int NumsOfCCABusy;
int NumsOfSendToChannel;
uint64_t NodeSendTimeStamp;
uint64_t NodeCcaTimeStamp;
uint64_t ACKAndIFSDuration; //发送结束后帧间间隔和ACK花费时间
uint64_t rate;
uint64_t ackWaitDuration;
int opticalClockDuration;
std::deque<uint64_t> packetSizeList;
std::deque<uint64_t> packetComeTimeStampList;
VLCChannel *channel;
};
class SuperFrame{
public:
SuperFrame(){
BO=9;
SO=8;
state=true; //true-active,false-sleep
opticalClockDuration=5000;
aBaseSuperframeDuration=60*16;
}
void start()
{
NS_LOG_FUNCTION(this);
//将superframe状态设置为true,这个状态表示活跃态CAP,false表示不活跃态sleep
//此CSMA代码不包含CFP阶段
state=true;
//将信道设置为空闲,信道状态分为三个,1忙碌,2空闲,3睡眠sleep,就是上面的不活跃态
channel->state=2;
//调用下面的方法,开始CAP阶段
CAPToSleep();
}
void CAPToSleep() //CAP start
{
NS_LOG_FUNCTION(this<<"CAP Start");
state=true;
channel->state=2;
// channel->state=1; //测试信道条件一直忙
uint64_t SD=aBaseSuperframeDuration*pow(2,SO)*opticalClockDuration;
uint64_t aSlotDuration=SD/16;
uint64_t nowTime=Simulator::Now().GetNanoSeconds();
// NS_LOG_DEBUG("nowTime="<<nowTime);
// NS_LOG_DEBUG("SD="<<SD);
// NS_LOG_DEBUG("aSlotDuration="<<aSlotDuration);
//一共有十六个时隙,所以要循环16次,根据信标beacon时间,定位接下来每一帧的开始时间
for(int i=0;i<16;i++)
{
channel->everySlotStartTimeStamp[i]=nowTime+aSlotDuration*i;
// NS_LOG_DEBUG("everySlotStartTimeStamp"<<channel->everySlotStartTimeStamp[i]);
}
// NS_LOG_DEBUG("CAP duration"<<SD);
//定义一个节点迭代器,对节点进行迭代
std::vector<VLCNode *>::iterator it;
//每个节点执行CAP重传接入,可跳到CAPRestartAccess阅读
for(it=m_Nodes.begin();it!=m_Nodes.end();it++)
{
(*it)->CAPRestartAccess();
}
Simulator::Schedule(NanoSeconds(SD),&SuperFrame::SleepToCAP,this);
}
void SleepToCAP() //start Sleep
{
NS_LOG_FUNCTION(this<<"Start Sleep");
state=false;
std::vector<VLCNode *>::iterator it;
for(it=m_Nodes.begin();it!=m_Nodes.end();it++)
{
if((*it)->RandomAccessing)
{
(*it)->suspend();
}
}
channel->state=3;
uint64_t SD=aBaseSuperframeDuration*pow(2,SO)*opticalClockDuration;
uint64_t BI=aBaseSuperframeDuration*pow(2,BO)*opticalClockDuration;
uint64_t SleepTime=BI-SD;
// NS_LOG_DEBUG("Sleep duration"<<SleepTime);
Simulator::Schedule(NanoSeconds(SleepTime),&SuperFrame::CAPToSleep,this);
}
int BO;
int SO;
bool state; //true-active,false-sleep
int aBaseSuperframeDuration;
int opticalClockDuration;
std::vector<VLCNode *> m_Nodes;
VLCChannel *channel;
};
int allPacketNums=0;
void testAddPacket(VLCNode *nodeId,int packetSize)
{
nodeId->packetSizeList.push_back(packetSize);
nodeId->packetComeTimeStampList.push_back(Simulator::Now().GetNanoSeconds());
}
void DelayMean(VLCChannel *channel)
{
double sum=0;
double mean=0;
for(unsigned int i=0;i<channel->AllPacketDelayVector.size();i++)
{
sum=sum+channel->AllPacketDelayVector.at(i);
}
mean=(double)sum/(channel->AllPacketDelayVector.size());
NS_LOG_INFO("the delay Mean="<<mean<<",nums of packet="<<allPacketNums);
NS_LOG_INFO("the num of node1 failure:"<<channel->nodes[1]->NumOfLostPackets);
NS_LOG_INFO("the num of node2 failure:"<<channel->nodes[2]->NumOfLostPackets);
NS_LOG_INFO("the num of collision:"<<channel->collisionTimes);
NS_LOG_INFO("the Throughput is:"<<(channel->SumOfSuccessSendPackets+12)*8/Simulator::Now().GetSeconds());
NS_LOG_INFO("node 1 Probability of collision:"<<(float)(channel->nodes[1]->numsOfCollision)/(float)(channel->nodes[1]->NumsOfSendToChannel));
NS_LOG_INFO("node 2 Probability of collision:"<<(float)(channel->nodes[2]->numsOfCollision)/(float)(channel->nodes[2]->NumsOfSendToChannel));
NS_LOG_INFO("node 3 Probability of collision:"<<(float)(channel->nodes[3]->numsOfCollision)/(float)(channel->nodes[3]->NumsOfSendToChannel));
NS_LOG_INFO("node 4 Probability of collision:"<<(float)(channel->nodes[4]->numsOfCollision)/(float)(channel->nodes[4]->NumsOfSendToChannel));
NS_LOG_INFO("node 5 Probability of collision:"<<(float)(channel->nodes[5]->numsOfCollision)/(float)(channel->nodes[5]->NumsOfSendToChannel));
NS_LOG_INFO("node 6 Probability of collision:"<<(float)(channel->nodes[6]->numsOfCollision)/(float)(channel->nodes[6]->NumsOfSendToChannel));
NS_LOG_INFO("node 7 Probability of collision:"<<(float)(channel->nodes[7]->numsOfCollision)/(float)(channel->nodes[7]->NumsOfSendToChannel));
NS_LOG_INFO("node 8 Probability of collision:"<<(float)(channel->nodes[8]->numsOfCollision)/(float)(channel->nodes[8]->NumsOfSendToChannel));
NS_LOG_INFO("node 9 Probability of collision:"<<(float)(channel->nodes[9]->numsOfCollision)/(float)(channel->nodes[9]->NumsOfSendToChannel));
NS_LOG_INFO("node 10 Probability of collision:"<<(float)(channel->nodes[10]->numsOfCollision)/(float)(channel->nodes[10]->NumsOfSendToChannel));
// float SumPofCollision=(float)(channel->nodes[1]->numsOfCollision)/(float)(channel->nodes[1]->NumsOfSendToChannel)+
// (float)(channel->nodes[2]->numsOfCollision)/(float)(channel->nodes[2]->NumsOfSendToChannel)+
// (float)(channel->nodes[3]->numsOfCollision)/(float)(channel->nodes[3]->NumsOfSendToChannel)+
// (float)(channel->nodes[4]->numsOfCollision)/(float)(channel->nodes[4]->NumsOfSendToChannel)+
// (float)(channel->nodes[5]->numsOfCollision)/(float)(channel->nodes[5]->NumsOfSendToChannel);
int j=0;
float SumPofCollision=0;
for(int i=1;i<11;i++)
{
if((channel->nodes[i]->NumsOfSendToChannel)!=0)
{
SumPofCollision=SumPofCollision+(float)(channel->nodes[i]->numsOfCollision)/(float)(channel->nodes[i]->NumsOfSendToChannel);
j++;
}
}
float PofCollision=SumPofCollision/(float)(j);
NS_LOG_INFO("P of Collision:"<<PofCollision);
NS_LOG_INFO("node 1 Probability of CCABusy:"<<(float)(channel->nodes[1]->NumsOfCCABusy)/(float)(channel->nodes[1]->NumsOfCCA));
NS_LOG_INFO("node 2 Probability of CCABusy:"<<(float)(channel->nodes[2]->NumsOfCCABusy)/(float)(channel->nodes[2]->NumsOfCCA));
NS_LOG_INFO("node 3 Probability of CCABusy:"<<(float)(channel->nodes[3]->NumsOfCCABusy)/(float)(channel->nodes[3]->NumsOfCCA));
NS_LOG_INFO("node 4 Probability of CCABusy:"<<(float)(channel->nodes[4]->NumsOfCCABusy)/(float)(channel->nodes[4]->NumsOfCCA));
NS_LOG_INFO("node 5 Probability of CCABusy:"<<(float)(channel->nodes[5]->NumsOfCCABusy)/(float)(channel->nodes[5]->NumsOfCCA));
NS_LOG_INFO("node 6 Probability of CCABusy:"<<(float)(channel->nodes[6]->NumsOfCCABusy)/(float)(channel->nodes[6]->NumsOfCCA));
NS_LOG_INFO("node 7 Probability of CCABusy:"<<(float)(channel->nodes[7]->NumsOfCCABusy)/(float)(channel->nodes[7]->NumsOfCCA));
NS_LOG_INFO("node 8 Probability of CCABusy:"<<(float)(channel->nodes[8]->NumsOfCCABusy)/(float)(channel->nodes[8]->NumsOfCCA));
NS_LOG_INFO("node 9 Probability of CCABusy:"<<(float)(channel->nodes[9]->NumsOfCCABusy)/(float)(channel->nodes[9]->NumsOfCCA));
NS_LOG_INFO("node 10 Probability of CCABusy:"<<(float)(channel->nodes[10]->NumsOfCCABusy)/(float)(channel->nodes[10]->NumsOfCCA));
// float SumPofCCABusy=(float)(channel->nodes[1]->NumsOfCCABusy)/(float)(channel->nodes[1]->NumsOfCCA)+
// (float)(channel->nodes[2]->NumsOfCCABusy)/(float)(channel->nodes[2]->NumsOfCCA)+
// (float)(channel->nodes[3]->NumsOfCCABusy)/(float)(channel->nodes[3]->NumsOfCCA)+
// (float)(channel->nodes[4]->NumsOfCCABusy)/(float)(channel->nodes[4]->NumsOfCCA)+
// (float)(channel->nodes[5]->NumsOfCCABusy)/(float)(channel->nodes[5]->NumsOfCCA);
float SumPofCCABusy=0;
for(int i=1;i<=j;i++)
{
SumPofCCABusy=SumPofCCABusy+(float)(channel->nodes[i]->NumsOfCCABusy)/(float)(channel->nodes[i]->NumsOfCCA);
}
float PofCCABusy=SumPofCCABusy/(float)(j);
NS_LOG_INFO("P of CCABusy:"<<PofCCABusy);
std::ofstream out("5NodeWithMean.txt",std::ios::app);
out<<(channel->SumOfSuccessSendPackets+12)*8/Simulator::Now().GetSeconds()<<" "
<<PofCollision<<" "<<PofCCABusy<<std::endl;
}
//void TestCapPacketCome(VLCNode *node,SuperFrame *superFrame)
//{
// if(superFrame->state)
// {
// node->PacketCome(500);
// }
//}
//*****************************************************************problem******************************************************************************
void PacketExponentialCome(VLCNode *node,double mean)
{
double nextPacketComeInterval;
Ptr<ExponentialRandomVariable> interval=CreateObject<ExponentialRandomVariable>();
double bound=40.0;
interval->SetAttribute("Mean",DoubleValue(mean));
interval->SetAttribute("Bound",DoubleValue(bound));
nextPacketComeInterval=interval->GetValue();
// if(node->channel->state!=3)
// {
allPacketNums++;
node->PacketCome(100);
// }
Simulator::Schedule(Seconds(nextPacketComeInterval),&PacketExponentialCome,node,mean);
}
//这是CSMA代码的主函数
int
main (int argc, char *argv[])
{
long int mean=1;
CommandLine cmd;
cmd.AddValue("mean","the mean packet",mean);
cmd.Parse(argc,argv);
Time::SetResolution (Time::NS);
RngSeedManager::SetSeed(time(0));
LogComponentEnable ("MacCsma", LOG_LEVEL_INFO);
LogComponentEnable("MacCsma", LOG_PREFIX_TIME);
uint64_t opticalClockDurationValue;
opticalClockDurationValue=5000;
SuperFrame superFrame;
superFrame.opticalClockDuration=opticalClockDurationValue;
VLCChannel channel;
VLCNode node1;
node1.NodeId=1;
node1.opticalClockDuration=opticalClockDurationValue;
VLCNode node2;
node2.NodeId=2;
node2.opticalClockDuration=opticalClockDurationValue;
VLCNode node3;
node3.NodeId=3;
node3.opticalClockDuration=opticalClockDurationValue;
VLCNode node4;
node4.NodeId=4;
node4.opticalClockDuration=opticalClockDurationValue;
VLCNode node5;
node5.NodeId=5;
node5.opticalClockDuration=opticalClockDurationValue;
VLCNode node6;
node6.NodeId=6;
node6.opticalClockDuration=opticalClockDurationValue;
VLCNode node7;
node7.NodeId=7;
node7.opticalClockDuration=opticalClockDurationValue;
VLCNode node8;
node8.NodeId=8;
node8.opticalClockDuration=opticalClockDurationValue;
VLCNode node9;
node9.NodeId=9;
node9.opticalClockDuration=opticalClockDurationValue;
VLCNode node10;
node10.NodeId=10;
node10.opticalClockDuration=opticalClockDurationValue;
node1.channel=&channel;
node2.channel=&channel;
node3.channel=&channel;
node4.channel=&channel;
node5.channel=&channel;
node6.channel=&channel;
node7.channel=&channel;
node8.channel=&channel;
node9.channel=&channel;
node10.channel=&channel;
channel.nodes[1]=&node1;
channel.nodes[2]=&node2;
channel.nodes[3]=&node3;
channel.nodes[4]=&node4;
channel.nodes[5]=&node5;
channel.nodes[6]=&node6;
channel.nodes[7]=&node7;
channel.nodes[8]=&node8;
channel.nodes[9]=&node9;
channel.nodes[10]=&node10;
superFrame.channel=&channel;
superFrame.m_Nodes.push_back(&node1);
superFrame.m_Nodes.push_back(&node2);
superFrame.m_Nodes.push_back(&node3);
superFrame.m_Nodes.push_back(&node4);
superFrame.m_Nodes.push_back(&node5);
superFrame.m_Nodes.push_back(&node6);
superFrame.m_Nodes.push_back(&node7);
superFrame.m_Nodes.push_back(&node8);
superFrame.m_Nodes.push_back(&node9);
superFrame.m_Nodes.push_back(&node10);
//此时,调用superframe的start方法,让它先运行起来,但是此时,包还没来,
//startrandomaccess()方法没有什么可执行的,跳到了start()方法继续阅读。
superFrame.start();
double exponentialMean=0.005;
std::ofstream out("NodeChanges.txt",std::ios::app);
out<<exponentialMean<<" ";
out.flush();
//当运行到相应时间的时候,各个节点陆续有包到达了,开始正常的竞争接入随机接入过程
Simulator::Schedule(Seconds(3.1),&PacketExponentialCome,&node1,exponentialMean);
Simulator::Schedule(Seconds(4.5),&PacketExponentialCome,&node2,exponentialMean);
Simulator::Schedule(Seconds(3.5),&PacketExponentialCome,&node3,exponentialMean);
Simulator::Schedule(Seconds(3.8),&PacketExponentialCome,&node4,exponentialMean);
Simulator::Schedule(Seconds(3.4),&PacketExponentialCome,&node5,exponentialMean);
Simulator::Schedule(Seconds(4.6),&PacketExponentialCome,&node6,exponentialMean);
Simulator::Schedule(Seconds(4.2),&PacketExponentialCome,&node7,exponentialMean);
Simulator::Schedule(Seconds(4.7),&PacketExponentialCome,&node8,exponentialMean);
Simulator::Schedule(Seconds(3.3),&PacketExponentialCome,&node9,exponentialMean);
Simulator::Schedule(Seconds(3.9),&PacketExponentialCome,&node10,exponentialMean);
// Simulator::Schedule(Seconds(3.1),&VLCNode::PacketCome,&node1,500);
// Simulator::Schedule(Seconds(3.3),&VLCNode::PacketCome,&node2,600);
// Simulator::Schedule(Seconds(2.4999),&testAddPacket,&node1,500);
// Simulator::Schedule(Seconds(2.4999),&testAddPacket,&node2,600);
// Simulator::Schedule(Seconds(2.5),&VLCNode::CCA,&node1);
// Simulator::Schedule(Seconds(2.5),&VLCNode::CCA,&node2);
//预定执行到499秒的时候,执行以下delaymean方法,这个方法是输出前面统计结果的一个函数
//在最终结束之前,将所有结果输出到屏幕上
Simulator::Schedule(Seconds(499),&DelayMean,&channel);
//预定一个停止的时间,为500秒,这里的时间是一个虚拟的时间,比真实的时间更快
Simulator::Stop(Seconds(500));
//进入死循环,如果没有stop上面方法的约束,会一直执行下去
Simulator::Run ();
//释放资源
Simulator::Destroy ();
return 0;
}