Getting Started tutorial NS3 and NS3 IEEE 802.15.7 CSMA / CA simulation code

 The original intention of this article

When I found that I had to do NS3 network simulation, my heart is rejected, on the one hand NS3 absolutely no contact, on the other hand, C ++ language contact is not too much, I feel a big workload. But, really it does not. Then I went to the Internet to check some simulations about what the content of NS3, entry, I feel really good chaos ah, this thing without a clear tutorial, are some of the clutter CSDN and technology blog, it seems very confusing, and some existing code are a lot of good years ago, make it difficult subject. So, I wrote this article, I hope you can help, stop and scratch back and see.

The first step in using a linux system

Now that you are ready for the NS3 simulation, the first stop and then install a NS3 it, but NS3 are running linux system, so, you have to install a linux system. linux system you can install directly to your computer, of course, you can also use the linux virtual machine installation (I was installed on a virtual machine), recommended virtualization software is VMware, the software can create a virtual machine is that you can create a in the case of linux virtual system, so you can not affect their windows system, NS3 easy to use, you can Baidu VMware installation tutorial, you can use the following Baidu cloud my link to download and install. VMware is used here not go into details, installation and use is relatively easy.

Link: https: //pan.baidu.com/s/1vKbVrIKDqueMdywsYFzZqA 
extraction code: crv1 

The second step of the installation NS3

NS3 installed a lot of online tutorials, free to find, I'm using version 3.25

The third step is to find out NS3 development process

Select or develop the appropriate module: select the appropriate emulation module and simulation object according to the actual simulation scenarios: If a wired local area network (CSMA) or wireless local area network (Wi-Fi); if the mobile node (Mobility) required; what application (application); the need for energy (energy) management; what routing protocol (internet, aodv etc.); the need for animation and other visual interface (visualizer, netanim) and so on. If you want to build a network is a relatively new network, such as the delay tolerant network (DTN), etc., need to develop design protocols, such as routing protocols, mobile model, energy management model.

Network simulation script writing: With the appropriate module, you can build a network simulation environment, ns3 simulation supports two scripting languages: C ++ and Python, but API interface is the same in both languages, some may not provide the Python API interface. Ns3 simulation script written roughly as follows.

  1. Generating node: ns3 empty node corresponds to a computer housing, then give the computer hardware and software required to install a network, such as network cards, applications, protocol stacks.
  1. Installation network devices: different networks have different types of network devices, thereby providing a different channel, the physical layer and the MAC layer, such as CSMA, WiFi, WiMAX, and point-to-point like.
  2. Installation Stack: ns3 network is typically TCP / IP protocol stack, selection of a particular stack, the case of TCP or UDP based network, which different routing protocols (OLSR, AODV, and Global etc.) to select and configure the appropriate IP address , ns3 which is to support IPv4 also support IPv6.
  3. Installing an application layer protocol: Select the appropriate application layer protocol based transport layer protocol of choice, but sometimes you need to write your own application layer network traffic code.
  4. Start the simulation.

Wherein the basic concepts of nodes, the network device, the channel, the application can refer to the following articles

https://blog.csdn.net/weichanghu_/article/details/83306998

The fourth step look at the time of scheduling mechanism NS3

https://blog.csdn.net/rustfree/article/details/84558058

The fifth step NS3 official website gave first.cc point, the example of CSMA and wifi

Through this example you can learn about the development process of a

https://www.docin.com/p-2009136480.html

The sixth step NS3 API

This time around the framework of NS3 should have almost, then you can try to look at the following code, and then the documentation will define some special class of some NS3, you can find here, and some models, you can also find here it is worth noting that this API and some old, some features have changed, such as the use of a random variable index.

https://www.nsnam.org/docs/release/3.7/doxygen/annotated.html

Step Seven 80215.7CSMA / CA code (for study and reference, not the whole letter, there may be an error not found)

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

 

Published 415 original articles · won praise 434 · views 210 000 +

Guess you like

Origin blog.csdn.net/qq_41901915/article/details/102954631