我正在尝试模拟Pure Aloha协议。经过一些研究,我理解了这个协议的工作原理简而言之,假设我们有5个节点并且帧大小是固定的。所有节点共享一个通道。当节点有数据要发送时,它会通过通道发送数据。如果两个或更多节点尝试同时(或在同一时间帧内)发送帧,则数据包冲突,并且每个节点必须再次重新发送该数据包。在随机时间之后,必须重新发送碰撞帧,这将降低再次发生碰撞的可能性。
这是我到目前为止所拥有的。我有五个节点[A-E]。这是五个站。每个节点都有自己的整数列表。这些是发送帧的时间。我生成了五个随机帧,我得到了这个结果: - 例如A 5,A 7,B 7,C 8,E 9.这些是随机生成的,并且意味着节点a具有两个帧以在时间= 5和时间= 7发送。帧B具有在时间= 7时发送的一个帧。由于我们有两个帧同时尝试发送帧,因此我们发生了冲突。
使用此代码我得到以下结果......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
namespace Test_v1
{
public class Simulation
{
Utility utils = new Utility();
static Random random = new Random();
private Timer t1;
int currentTime;
int frameSize; //frame size in bits.
int channelCapacity; //channel capacity in bits.
int frameTime; //time to transmit one frame on the channel in milliseconds.
private List<Node> nodeList;
Node A;
Node B;
Node C;
Node D;
Node E;
int collisions = 0;
public Simulation()
{
frameSize = 10;
channelCapacity = 100;
frameTime = (frameSize / channelCapacity) * 100;
nodeList = new List<Node>();
A = new Node(); A.stationName = "Station A";
B = new Node(); B.stationName = "Station B";
C = new Node(); C.stationName = "Station C";
D = new Node(); D.stationName = "Station D";
E = new Node(); E.stationName = "Station E";
nodeList.Add(A);
nodeList.Add(B);
nodeList.Add(C);
nodeList.Add(D);
nodeList.Add(E);
generateFrames(5);
t1 = new Timer(100);
t1.Elapsed += new ElapsedEventHandler(IntervalTimerElapsed);
t1.Start();
}
protected void IntervalTimerElapsed(object sender, EventArgs e)
{
int framesOnChannel = 0;
foreach (Node n in nodeList)
{
for (int i = 0; i < n.queue.Count; i++)
{
if (currentTime == n.queue[i])
{
Console.WriteLine(currentTime + " " + n.stationName + " " + n.queue[i]);
framesOnChannel = framesOnChannel + 1;
collisions = collisions + 1;
if(framesOnChannel > 1)
n.queue[i] = BackOff(n) + currentTime;
}
else
{
Console.WriteLine(currentTime);
}
}
}
currentTime++;
if (framesOnChannel > 1)
{
Console.WriteLine("Frames on Channel:" + framesOnChannel + " Collision!");
}
else
{
Console.WriteLine("Frames on Channel:" + framesOnChannel);
}
framesOnChannel = 0;
if (currentTime > 10)
t1.Stop();
}
private void generateFrames(int load_G)
{
for (int i = 0; i < load_G; i++)
{
Node randomStation = getRandomNode();
randomStation.queue.Add(utils.RandomNumber(0, 10));
}
foreach (Node n in nodeList)
{
n.queue.Sort();
}
}
private int BackOff(Node node)
{
int k = node.attempts;
if (k > 10)
k = 10;
int R = (int)Math.Round(Math.Pow(2, k) - 1);
int backOffTime = random.Next(0, R) * frameTime;
return backOffTime + (frameTime * 2);
}
private Node getRandomNode(){
switch (random.Next(1, 6))
{
case 1:
return A;
case 2:
return B;
case 3:
return C;
case 4:
return D;
default:
return E;
}
}
}
}
到目前为止,我已设法检测到何时发生碰撞。 a)我需要以某种方式将Backoff方法应用于那些在未来时间碰撞并发送它们的节点。当检测到碰撞但没有任何反应时,我应用了退避。在这种情况下,所有帧都应该发生冲突,因为要成功传输帧,必须只有一帧时间为两个滴答。
b)我需要计算成功的传输。如果在2个刻度内没有发送其他帧,则传输成功。例如,如果在时间= 1发送帧,则在time = 1到time = 3内必须没有其他帧才能成功。
提前感谢您的帮助。如果问题不明确,请告诉我。
答案 0 :(得分:4)
假设您要创建单线程模拟,您有两种选择 - 时间驱动模拟,或事件驱动模拟。两者之间的区别在于模拟时间(或模拟时钟)的进展方式。时间进展的方式决定了模拟的运作方式:
<强> 1。时间驱动的模拟
在时间驱动模拟中,时间连续运行,并在时序循环中通过小的离散值递增。定时循环递增模拟时钟并迭代模拟的每个组件(例如节点,通道等),询问每个人当前 是否想要做某事。
模拟组件根据当前模拟时间(由定时循环传递)及其预定义行为做出决策。例如,节点可能决定在模拟时间A,B和C发送数据包。
完成每次迭代后,定时循环将模拟时间提前一小部分并重新开始。在这个模型中,为了创建一个很好的实际时间近似值,时间增量必须非常小。
<强> 2。事件驱动模拟
在事件驱动的模拟中,事情发生是因为是时候发生。时间不会有争议,但从一个偶数到下一个。在这样的模拟中,每个模拟元素(节点,消息,共享信道等)生成定时事件(例如“我需要在时间XXX发送分组”,或“消息在时间XXX到达”)。事件被放入一个按时间排序的队列中,计时循环一次一个地对事件进行排队。
每当事件被排队时,都会通过通知事件的所有相关实体来处理。例如,如果出队事件是“节点A在时间5通过信道C向节点B发送分组”,则通过向信道C通知所发送分组来处理该事件。当通知事件时,通道C可以反过来创建事件。例如,它可以创建一个新事件,其中显示“来自节点A的消息已在时间6通过通道C传送到节点B”,从而创建一个模拟,其中消息1模拟时间单位在通道上传播(从我的例子中的时间5到时间6)。这些响应事件被放回队列中,并按时间排序。
接下来,定时循环仅对下一个事件进行排队,并将模拟时钟前进到下一个事件的时间。这样,如果长时间没有发生模拟事件,事件循环就会向前跳过,与时间驱动模拟不同。
这是一种(通常)更好,更有效的模拟系统方式,但它也稍微复杂一些。