纯Aloha协议的模拟

时间:2014-12-19 19:04:36

标签: c# .net network-programming simulation network-protocols

我正在尝试模拟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;
            }
        } 
    }
}

Output so far 到目前为止,我已设法检测到何时发生碰撞。 a)我需要以某种方式将Backoff方法应用于那些在未来时间碰撞并发送它们的节点。当检测到碰撞但没有任何反应时,我应用了退避。在这种情况下,所有帧都应该发生冲突,因为要成功传输帧,必须只有一帧时间为两个滴答。

b)我需要计算成功的传输。如果在2个刻度内没有发送其他帧,则传输成功。例如,如果在时间= 1发送帧,则在time = 1到time = 3内必须没有其他帧才能成功。

提前感谢您的帮助。如果问题不明确,请告诉我。

1 个答案:

答案 0 :(得分:4)

假设您要创建单线程模拟,您有两种选择 - 时间驱动模拟,或事件驱动模拟。两者之间的区别在于模拟时间(或模拟时钟)的进展方式。时间进展的方式决定了模拟的运作方式:

<强> 1。时间驱动的模拟

在时间驱动模拟中,时间连续运行,并在时序循环中通过小的离散值递增。定时循环递增模拟时钟并迭代模拟的每个组件(例如节点,通道等),询问每个人当前 是否想要做某事。

模拟组件根据当前模拟时间(由定时循环传递)及其预定义行为做出决策。例如,节点可能决定在模拟时间A,B和C发送数据包。

完成每次迭代后,定时循环将模拟时间提前一小部分并重新开始。在这个模型中,为了创建一个很好的实际时间近似值,时间增量必须非常小。

<强> 2。事件驱动模拟

在事件驱动的模拟中,事情发生是因为是时候发生。时间不会有争议,但从一个偶数到下一个。在这样的模拟中,每个模拟元素(节点,消息,共享信道等)生成定时事件(例如“我需要在时间XXX发送分组”,或“消息在时间XXX到达”)。事件被放入一个按时间排序的队列中,计时循环一次一个地对事件进行排队。

每当事件被排队时,都会通过通知事件的所有相关实体来处理。例如,如果出队事件是“节点A在时间5通过信道C向节点B发送分组”,则通过向信道C通知所发送分组来处理该事件。当通知事件时,通道C可以反过来创建事件。例如,它可以创建一个新事件,其中显示“来自节点A的消息已在时间6通过通道C传送到节点B”,从而创建一个模拟,其中消息1模拟时间单位在通道上传播(从我的例子中的时间5到时间6)。这些响应事件被放回队列中,并按时间排序。

接下来,定时循环仅对下一个事件进行排队,并将模拟时钟前进到下一个事件的时间。这样,如果长时间没有发生模拟事件,事件循环就会向前跳过,与时间驱动模拟不同。

这是一种(通常)更好,更有效的模拟系统方式,但它也稍微复杂一些。