我正在尝试模拟Pure Aloha协议。经过研究,我了解了该协议的工作原理。简而言之,假设我们有5个节点并且帧大小是固定的。所有节点共享一个通道。当节点有要发送的数据时,它通过通道发送数据。如果两个或两个以上的节点尝试同时(或在同一时间范围内)发送帧,则数据包冲突,每个节点必须再次重新发送数据包。冲突的帧将必须在随机时间后重新发送,这将降低再次发生冲突的可能性。
到目前为止,这就是我所拥有的。我有五个节点[A-E]。这是五个站。每个节点都有自己的整数列表。这些是发送帧的时间。我生成了五个随机帧,并得到以下结果:-例如A 5,A 7,B 7,C 8,E9。它们是随机生成的,表示节点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发送一个帧,则必须在时间= 1到时间= 3内没有其他帧才能成功。
在此先感谢您的帮助。如果不清楚,请告诉我。
最佳答案
假设您要创建一个单线程模拟,则有两种选择-时间驱动模拟或事件驱动模拟。两者之间的差异是模拟时间(或模拟时钟)前进的方式。时间推移的方式决定了模拟的运行方式:
1.时间驱动的模拟
在时间驱动的仿真中,时间连续运行,并在定时循环中以小的离散值递增。定时循环会增加模拟时钟并在模拟的每个组件(例如节点,通道等)上进行迭代,询问每个组件当前是否要执行某项操作。
仿真组件根据当前仿真时间(经过定时循环)及其预定义的行为来做出决策。例如,节点可能决定在模拟时间A,B和C发送数据包。
完成每次迭代后,定时循环将模拟时间提前固定的少量时间重新开始。在此模型中,要创建实际时间的近似值,时间增量必须非常小。
2.事件驱动的模拟
在事件驱动的仿真中,事情之所以发生,是因为现在该发生了。时间并没有争执地前进,而是从一个到另一个。在这种模拟中,每个模拟元素(节点,消息,共享通道等)都会生成定时事件(例如“我需要在XXX时发送数据包”,或者“消息已在XXX时到达”)。将事件放入按时间排序的队列中,并且定时循环一次将事件从队列中取出。
每当事件出队时,都通过通知事件的所有相关实体来处理。例如,如果出队事件是“节点A在时间5通过通道C将数据包发送到节点B”,则通过将已发送数据包通知通道C来处理该事件。获知事件后,通道C可以依次创建事件作为响应。例如,它可以创建一个新事件,说明“来自节点A的消息已在时间6处由通道C传递到节点B”,从而创建了一个仿真,其中它以1个仿真时间单位将消息传播到整个通道(在我的示例中是从时间5到时间6)。这些响应事件被放回到队列中,并按时间排序。
接下来,定时循环仅使下一个事件出队,并将模拟时钟提前到下一个事件的时间。这样,如果长时间没有发生模拟事件,则与时间驱动的模拟不同,事件循环只会向前跳过。
这是一种(通常)更好,更有效的模拟系统的方法,但它也稍微复杂一些。
关于c# - 纯Aloha协议(protocol)的仿真,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27572368/