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

10-10 17:08