clc
clear all
close all
Throughput_Result=zeros(1,11);
w=1;
for l=0:10000:100000
M=4; %无线节点数,其中AP号为M+1
%l=10000; %传播距离为10Km
c=3.0*10^8;
BER=10^(-6);%误码率
TotalTimeInSeconds=200; %总仿真时间,单位:秒
SlotTime=20*10^(-6);
PropTime=l/c/SlotTime;
TotalTime=TotalTimeInSeconds/SlotTime; %总仿真时隙100000,单位为slottime
PacketResendingRate=0; %数据包重发率
Counter=0; %数据包发送成功计算法
ChannelBusy=0; %信道是否繁忙标志
IdleTimer=0; %信道空闲时隙
%MaxResend=20;%最大重传次数
Start=0; %数据传输开始标志
Collition=0; %信道是否冲突标志
Throughput=0; %吞吐量
PacketResendingRate_Result = zeros(1,TotalTimeInSeconds);
Delay_Result = zeros(1,TotalTimeInSeconds);
DeferenceTime=0; %其他节点后退时间(NAV)
% Result=1:200;
Resend=zeros(1,M+1); %各个站点的重传次数
SendTime=zeros(1,M+1); %每个数据包发送时间向量
ArrivalTime=1:M; %新数据包到无线节点缓冲区的时间
%PacketLength=zeros(1,M+1); %到无线节点发送缓冲区的新数据包长度
HasPacket=zeros(1,M+1); %每个站点是否有数据发送
DelayBuff=zeros(1,10001); %AP转发缓冲区,内容为无线节点发送各数据包的时间
CW=1:M+1;
BackoffTimer=1:M+1; %每个站点的退避时间
PacketBuff=zeros(M+1,10001); %每个站点的数据缓冲大小,第一列表示有多少个数据包,第二列开始为每个数据包大小
CollitionStations=zeros(1,M+2); %竞争节点序列,第一列为竞争节点总数
%物理层采用802.11b标准,直接序列扩频
PhyRate=2*10^6; %物理层传输速率2Mbps
PLCP_hdr=48; %bits
PLCP_preamble=144; %bits
MAC_hdr=28*8; %bits
PHY_hdr=40*8; %bits
Hdr=(PHY_hdr + MAC_hdr)/(PhyRate*SlotTime); %帧头=物理帧头加MAC帧头
PLCP=(PLCP_hdr+PLCP_preamble)/(PhyRate*SlotTime);
SIFS=0.5+2*PropTime; %10us,单位为slottime
DIFS=SIFS+2; %50us,单位为slottime
ACK=(14*8+PHY_hdr)/(PhyRate*SlotTime); %以时隙为单位
RTS=(20*8+PHY_hdr)/(PhyRate*SlotTime);
CTS=(14*8+PHY_hdr)/(PhyRate*SlotTime);
CWmin=31; %最小退避窗口值
CWmax=1023; %最大退避窗口值
m=5; %最大退避级数
mm=7; %最大重传次数
%ACKTimeout=44*10^(-6)/SlotTime;
%CWbasic=512; %判断信道激烈程度的阈值
% Proptime=l/c/SlotTime; %传播时延,以时隙为单位
ACKTimeout=2*PropTime + SIFS +PLCP + 1; %ACK超时溢出
CTSTimeout=2*PropTime + SIFS + PLCP + 1; %RTS超时溢出
AverageArrivalTime=100; %平均到达时间间隔(slottime),服从指数分布
%AveragePacketLength=50; %平均数据包长度,服从指数分布
PacketLengthsize=8000; %数据包大小采用固定帧长,8000bits
PacketLength=PacketLengthsize/(PhyRate*SlotTime)*ones(1,M+1); %一个数据帧占用多少(200)个时隙
CurBufferSize=zeros(1,M+1); %当前每个站点缓冲区大小
Buffer_Threshold=8*10^6/(PhyRate*SlotTime); %最大缓冲区大小为1M Byte
%% 初始化进程Initial Process,该程序段中的ExpDis(value)为产生均值为value的指数分布的随机变量,实际以1000表示足够大
for i=1:M+1
ArrivalTime(i)=ExpDis(AverageArrivalTime); %包到达时间间隔
%PacketLength(i)=ExpDis(AveragePacketLength); %包的长度
CW(i)=CWmin; %初始化为最小竞争窗口
BackoffTimer(i)=1200; %初始化退避计数器值,代表无穷大
end
for t=1:TotalTime
for i=1:M+1
if t==ArrivalTime(i) %主机有数据要发送
if CurBufferSize(i) < Buffer_Threshold - PacketLength(i); %如果数据缓冲区的大小小于缓冲门限,把即将发送的数据压入缓冲区,否则丢弃
PacketBuff=Push(PacketBuff,i,PacketLength(i));
% PacketBuff=zeros(M,1501); M*1501的矩阵
%PacketBuff(1、2、M,1),作为压栈的序号
CurBufferSize(i) = CurBufferSize(i)+PacketLength(i); %更新目前缓冲区大小
ArrivalTime(i)=ExpDis(AverageArrivalTime) + t; %下一次包到达时间
HasPacket(i)=1; %有数据包等待发送U
end
end
if HasPacket(i)==1 & ChannelBusy==0 & BackoffTimer(i)==1200
IdleTimer=IdleTimer+1;
if IdleTimer==ceil(DIFS)
BackoffTimer(i)=RandSel(CW(i)); %随机退避计数器值
IdleTimer=0;
end
elseif HasPacket(i)==1 & ChannelBusy==0 & BackoffTimer(i)==0%有数据传输且信道空闲
CollitionStations=Add(CollitionStations,i);
%CollitionStations(1):冲突的站点数;CollitionStations(2,3,~):冲突的序列号;
%CollitionStations(1)=0,CollitionStations(2)表示要发送的主机号
if Resend(i)==0 %即是第一次发送的,不是重发的
SendTime(i)=t+DIFS;
end
Start=1; %开始进入数据传输阶段
elseif HasPacket(i)==1 & ChannelBusy==0 & BackoffTimer(i)>0 & BackoffTimer(i)<1200
BackoffTimer(i)=BackoffTimer(i)-1; %每经过一个空闲时隙,退避计数器值减1
end
end
%在信道处于空闲的情况下,退避计数器会逐次递减,所有站点处于竞争接入状态。
%一旦计数器退避至0,则标记为Start,表明可以开始传输,并将当前站点序号
%压入CollitionStations队列中,用以判断是否发生冲突。
%% 传输过程 Transfer Process采用RTS/CTS传输,解决长距离隐藏终端问题,考虑传播时延
if Start == 1
ChannelBusy=1; %此时有数据传输,信道繁忙
n=CollitionStations(1); %记录竞争站点数
DST=t+DIFS;%DATA SEND TIME
AAT=DST+2*PropTime+SIFS; %ACK ARRIVAL TIME
if AAT<=DST+CTSTimeout & n==1
%if n == 1
DeferenceTime=floor(t+RTS+CTS+Hdr+4*PropTime+DIFS+PacketBuff(CollitionStations(2),2)+ACK+3*SIFS);
% 其他节点需要等待的时间(NAV),成功发送的时间
Collition=0; %无竞争
else
DeferenceTime=floor(t+DIFS+PropTime+RTS);
Collition=1; %竞争状态
end
Start=0; %数据传输完成
end
%在传输过程中,首先标记信道忙,然后根据CollitionStations里存放的站点序号,判断当前是否发生冲突,
%如果没有冲突,则所有其他站点推迟时间DeferenceTime。长度保证让源站点和目的站点之间可以进行完整的通信过程。
%反之如果发生冲突,则推迟时间为最大的冲突帧的长度加DIFS
%% 更新过程 Update Process
if t==DeferenceTime & ChannelBusy==1 %信道为忙,且到达预定时间传输完成
if Collition==0
n = CollitionStations(2);
PER=1-(1-BER)^(PacketBuff(n,2)*PhyRate*SlotTime); %误包率
AckER=1-(1-BER)^(ACK*PhyRate*SlotTime); %ACK误包率,ACK以时隙为单位
if rand>=PER & rand>=AckER
PacketLost=0; %无错误
else
PacketLost=1;
end
end
if Collition==0 &PacketLost==0 %发送成功
n=CollitionStations(2); %已传输完成的站点
CurBufferSize(n)=CurBufferSize(n) - PacketBuff(n,2); %已传输完成,将其从缓冲队列中取出(丢弃)
Throughput=Throughput + PacketBuff(n,2)*SlotTime*PhyRate;
Counter=Counter+1;
% else %STA的数据包发送到AP
% if CurBufferSize(M+1) < Buffer_Threshold - PacketBuff(n,2)
% if BackoffTimer(M+1)==1200 %表示AP的发送缓冲原来没有数据
% BackoffTimer(M+1)=RandSel(CW(M+1));
% end
% PacketBuff=Push(PacketBuff,M+1,PacketBuff(n,2));
% CurBufferSize(M+1)=CurBufferSize(M+1)+PacketBuff(n,2);
% HasPacket(M+1)=1;
% ST=SendTime(n);
%
% Resend(n)=0;
% end
% end
PacketBuff=Pop(PacketBuff,n);
CW(n)=CWmin; %初始化竞争窗口值
k=PacketBuff(n,1); %栈头的值,表示栈中数据包的数量,k=1表示栈中有一帧数据没有发送,依次类推;
if k==0 %栈没有数据要发送
HasPacket(n)=0;
BackoffTimer(n)=1200; %恢复初始值
else
BackoffTimer(n)=1200; %有数据继续发送,重新选择随机退避窗口值
end
else %发送失败
PacketRensendingRate=PacketResendingRate+1;
n=CollitionStations(1); %发生碰撞,传输失败
for i=1:n
j=CollitionStations(i+1); %发生碰撞的站点数
Resend(j)=Resend(j)+1;
if Resend(j)<m; %退避阶数增加
CW(j