Aloha:夏威夷人问候语,欢迎,再见。它还有另一层意思,是‘I love you’。当然这是根据语境来分析的,如果没有语境分析,我想它也不会存在那么多意思。表达'I love you'的时候,Aloha发音要延长点,a....lo...ha。大家可以试试。好了,还是回归正题吧。Aloha协议是什么?它可以解决什么样的问题?
Aloha协议是分配一个多路访问信道的协议,而要解决的问题当然也就是它的目的,怎么分配信道才能使网络带宽利用率更高,网络延迟更低。
Aloha协议有两种:纯Aloha协议和分槽Aloha协议。
纯Aloha协议:当用户有数据需要发送时就传输。显然,这种协议在单路信道上很容易发生冲突。当两个或多个用户需要发送数据时,冲突就发生了,然后他们都需要开始重传,直到没有冲突发生。这种协议的效率会如何呢?现在我们假定每个站产生的新帧可以模型化为一个平均每帧时产生N个帧的泊松分布。如果不期望发生冲突,就需要期望N不大于1。不然N大于1,肯定有多个站在一个帧时内同时发送,这就会导致冲突,然后信道效率也就会开始降低。
如图,我们可知道,如果在t0~t0+2t时间段内,除了阴影帧外还有其它帧产生的话就会发生冲突。即易受冲突的时间为2t。
在给定一个帧时内,我们期望有G帧,而每帧时期望生成k帧的概率服从泊松分布:
一帧时内生成0帧的概率为。两帧时内生成0帧的概率为
。根据上面的图可知,如果两帧时内生成0帧,那么就可以成功传输一帧。从而可知信道利用率。可以计算出来,G=0.5时,信道利用率最高为S=1/2e=0.184。(求导可得解)
分槽Aloha协议:将时间划分为时间槽,每个站只能在时间槽开始的时候发送数据。这样,易受冲突时间就会从原来的2t变为t,传送成功率增长了一倍变为。相应的,信道利用率S也增长了一倍变为0.368。
概念性的问题差不多就这些了,对了,还差个仿真的概念。什么是仿真?仿真就是模拟实际,而实际当中的变化又无从可知,所以仿真就需要建立在一定事实基础上再进行随机化实验。总之就一句话,随机实验。
下面重点分析下Aloha分槽协议仿真。
实验环境:win8系统 、eclipse开发环境、java语言编写
实验重点:模拟时间槽划分时间,判断每个时间槽有几个帧。时间槽可以用整数变量来操控,其它每个·站发送数据的时间也可以用整数代替。判断一个时间槽有几个帧,可以先对每个站发送数据的时间从小到大排序,然后再根据时间槽的范围,判断有几个站在这个时间槽发送数据。如果有两个或以上的站发送数据,那么相应站就再随机产生发送时间,记录此时有多少个帧;如果只有一个,那么就发送成功,成功发送帧数+1。如果为0帧,就继续下一个时间槽。重复以上步骤,直到成功发送数据到达预期的值。
源码:
Data.java
public class Data {
public int time;
public Data(int time){
this.time = time;
}
public void set(int time){
this.time = time;
}
}
Aloha.java
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
public class Aloha extends JFrame{
//站点基数为1
public static int base = 1;
//站点总数
public int MaxStation;
//时间段需要设置比较长,不然每个时间槽的冲突的可能很大,也就无法仿真了
public final int randTime = 1000;
//successPost越大,越接近真实情况,曲线也越清晰
private int successPost = 1000;
//时间槽大小
public final int time = 2;
//帧的总数
public int countPoint = 0;
//站队列
private List<Data> list;
//画布
private Graphics g;
//设置最大发送站点数
public void setNum(int num){
this.MaxStation = num;
}
//仿真函数
public void GetStatus() {
Random r = new Random();
int total = 0;
int success = 0;
list = new ArrayList<Data>();
//随机产生站点发送数据时间
for (int i = 0; i < MaxStation; i++) {
Data d = new Data(r.nextInt(randTime)+1);
list.add(d);
}
//发送时间排序
Comparator<Data> comparator = new Comparator<Data>() {
public int compare(Data d1, Data d2) {
return d1.time - d2.time;
}
};
Collections.sort(list,comparator);
int count = 0; //记录经历过的时间周期
while(true){
int temcount = 0; //记录每个时间槽发送帧的次数
for(int i = 0; i < MaxStation; i++){
if(list.get(i).time >= count * time && list.get(i).time <= (count+1)*time){
total += 1;
temcount += 1;
}else{
break;
}
}
count++;
if(temcount == 0){ //没有帧
//continue;
}else if(temcount == 1){ //成功发送数据
success += 1;
list.get(0).set(r.nextInt(randTime)+1+count*time);
if(success > successPost){
break;
}
}else if(temcount > 1){ //冲突,在随机产生发送数据时间
for(int j = 0; j < temcount; j++){
list.get(j).set(r.nextInt(randTime)+1+count*time);
}
}
Collections.sort(list,comparator);
}
drawPoint((int)((1.0 * total/count)* 70 + 100), (int)(400-(10.0 * success/count)*29));
// System.out.println("每包时的尝试次数:"+(1.0 * total/count));
// System.out.println("吞吐量:"+(1.0*success/count));
}
public static void main(String[] args) {
Aloha aloha = new Aloha();
aloha.initUI(); //初始化UI
int i = 0;
while(true){
i++;
aloha.setNum(base*i); //增加站点数
aloha.GetStatus();
}
}
public void paint(Graphics g){
super.paint(g);
draw(g);
}
//初始化界面
public void draw(Graphics g){
g.setColor(Color.RED);
g.drawLine(100, 400, 500, 400);
g.drawLine(100,100,100,400);
g.drawString("0", 90, 405);
for(int i = 1; i <= 5; i++){
g.drawString("|", 100+70*i, 398);
g.drawString(i+"", 100+70*i, 413);
}
g.drawString("G(每包时尝试次数)", 260,430);
for(int i = 1; i <= 10; i++){
g.drawString("-", 100 , 400-29*i);
if(i != 10){
g.drawString("0."+i, 80 , 400-29*i);
}else{
g.drawString(i/10+".0", 80 , 400-29*i);
}
}
int Stringx = 60;
int Stringy = 180;
g.drawString("每", Stringx, Stringy);
g.drawString("包", Stringx, Stringy+14);
g.drawString("时", Stringx, Stringy + 14*2);
g.drawString("的", Stringx, Stringy + 14*3);
g.drawString("吞", Stringx, Stringy + 14*4);
g.drawString("吐", Stringx, Stringy + 14*5);
g.drawString("量", Stringx, Stringy + 14*6);
g.drawString("S", Stringx, Stringy + 14*7+10);
g.setColor(Color.BLACK);
}
//话点
public void drawPoint(int x,int y){
g.drawLine(x, y, x, y);
}
//初始化界面参数
public void initUI(){
FlowLayout f1 = new FlowLayout();
this.setTitle("Aloha协议");
this.setLayout(f1);
this.setSize(640,480);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.g = this.getGraphics();
}
}
效果截图:
可以看出,分槽Aloha协议信道利用率可以达到0.368左右。但是,我们远不满足这样的一个利用率,效率太低。后来的CSMA协议,可以到达到更高的效率。尤其是0.01-坚持CSMA,它的效率可以接近100%。有兴趣的可以了解下,我就不在此细说了。