用於在多路訪問信道上確定下一個使用者的協議屬於數據鏈路層的一個子層,稱爲介質訪問控制(Medium Access Control,MAC)子層,許多局域網都使用多路訪問信道作爲它的通信基礎。最簡單的信道分配方案是FDM(爲每個站專門分配一段頻率)和TDM(爲每個站分配一個時槽),當站的數量比較大而且可變,或者流量具有突發性變化的時候,就需要用到純ALOHA協議或分槽ALOHA協議。如果信道的狀態可以被檢測到,可以用到1-堅持型CSMA、非堅持CSMA和P-堅持CSMA等協議。
設置各站點初始產生包的時間點及產生包的時間間隔(均爲隨機值),得到所有站點成功發送10000個數據包的總時間以及這段時間內所有數據包的個數(包括各站點每次新產生的包以及由於衝突而重發的包),從而計算出每包時內嘗試次數及其對應的吞吐量。針對不同的包產生間隔,得到不同的每包時內嘗試次數及其對應的吞吐量,將其畫成一條曲線。
一、 實現原理
實現原理:分槽Aloha的基本思想是把信道時間分成離散的時間槽,槽長爲一個幀所需的發送時間。每個站點只能在時槽開始時才允許發送。其他過程與純ALOHA協議相同。分槽Aloha的信道效率比純Aloha要高。分槽Aloha的易受衝突區比純Aloha小了一半。它的重發策略是等待一段隨機的時間,然後重發;如再次衝突,則再等待一段隨機的時間,直到重發成功爲止,但是發送的時間也是在每個時間槽的開始。
二、 具體設計
代碼包括五個類:
AlohaThread.java, CountslotNum.java, SendPot.java,time.java, Main.java。
Main.java是主類。主要是負責時間槽的初始化,以及多個線程的啓動。
SendPot.java是發送站類。負責初始化每個站點發送的時間、時間間隔,其中包括槽時間間隔以及真正的時間間隔。
AlohaThread.java是實現了Thread接口的類。他是Aloha的線程,run方法裏面寫了判斷衝突的方法和數據包發送的計數方法。每一個線程都是一個SendPot的發送過程。
CountslotNum.java同樣實現了Thread接口的類。它的功能是用來記錄時間槽進行的時間。
1.Main.java
package Aloha;
import java.util.ArrayList;
public class Main {
public static void main(String[] args){
int[] a = new int[10000];
for (int i = 0; i < 100000; i++) {
time t = new time();
t.setN(i);
t.setCount(0);
}
for (int i = 0; i < a.length; i++) {
a[i] = 0;
}
SendPot sp1 = new SendPot(1);
SendPot sp2 = new SendPot(2);
SendPot sp3 = new SendPot(3);
SendPot sp4 = new SendPot(4);
SendPot sp5 = new SendPot(5);
SendPot sp6 = new SendPot(6);
CountslotNum c = new CountslotNum();
c.start();
AlohaThread at1 = new AlohaThread(sp1,c,a,100);
AlohaThread at2 = new AlohaThread(sp2,c,a,100);
AlohaThread at3 = new AlohaThread(sp3,c,a,100);
AlohaThread at4 = new AlohaThread(sp4,c,a,100);
AlohaThread at5 = new AlohaThread(sp5,c,a,100);
AlohaThread at6 = new AlohaThread(sp6,c,a,100);
at1.start();
at2.start();
at3.start();
at4.start();
at5.start();
at6.start();
}
}
2.AlohaThread.java
package Aloha;
import java.util.Random;
public class AlohaThread extends Thread{
private SendPot sp;
private Random r = new Random();
private long temp;
private CountslotNum c;
private int[] a;
private int num;
private int count=0;
public AlohaThread(SendPot sp,CountslotNum c,int[] a,int num){
this.sp = sp;
this.c = c;
this.a = a;
this.num=num;
}
public void run(){
try {
Thread.sleep(sp.mtime());
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for (int idx = 0; idx < num; idx++) {
a[c.getN()] = a[c.getN()]+1;//衝突
try {
Thread.sleep(1);
//衝突回退
while(a[c.getN()]>1) {
temp = r.nextInt(5)+1;
long next_time=temp+c.getN();
count++;
System.out.println(sp.getNum()+"衝突,下一次發送的時間點爲:"+next_time);
System.out.println(sp.getNum()+"的第"+count+"衝突");
Thread.sleep(temp*20);
}
long next_time=c.getN()+sp.getDT();
System.out.println("發送成功:第"+sp.getNum()+"號第"+idx+"個數據包~"+"下一次發送的時間點爲:"+next_time);
Thread.sleep(sp.getD());
if(idx==num-1){
count=count+num;
double t1=count*sp.getDT();
double traffic=t1/c.getN();
System.out.println("第"+sp.getNum()+"號每包時內傳輸次數:"+traffic);
double t2=num*sp.getDT();
double thoughput=t2/c.getN();
System.out.println("第"+sp.getNum()+"號吞吐量:"+thoughput);
}
} catch (Exception e) {
}
}
}
}
3.SendPot.java
package Aloha;
import java.util.Random;
public class SendPot {
private Random r = new Random();
private int Num;
//開始發送時間
private long mgtime;
//時間間隔
private long d;
private long slot=20;//槽時間間隔
public SendPot(int Num){
this.Num = Num;
mgtime = r.nextInt(1000);
d = r.nextInt(30)+20;
}
public int getNum() {
return Num;
}
public long mtime() {
return (mgtime/slot+1)*slot;//各站點數據包發送時間點,歸併到時槽的開始處
}
public long getD() {//真正間隔時間
return (d/slot+1)*slot;
}
public long getDT() {//間隔槽片段
return (d/slot+1);
}
}
4.CountslotNum.java
package Aloha;
public class CountslotNum extends Thread{
private int N;
public static int timecount=20;
public static void main(String[] args){
CountslotNum j=new CountslotNum();
j.start();
}
public void run(){//時間槽的計數,在這裏時間槽按照線性事件遞增,爲一獨立進程
while(true){
try {
N = N+1;
System.out.println("時間槽計數:"+N);
Thread.sleep(timecount);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getN(){
return N;
}
}
5.time.java
package Aloha;
public class time {
//第N個時槽
private int N;
//需要發送的數目
private int count;
public int getN() {
return N;
}
public void setN(int n) {
N = n;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}