static void Main(string[] args) { var simulator = new Simulator() { MaxNetworkSpeed = 5 << 10, SimulationInterval = 500 }; // initialize two devices and register them to the network var d1 = new Device() { Name = "D1" }; var d2 = new Device() { Name = "D2" }; simulator.Register(d1, null); simulator.Register(d2, new int[] { d1.ID }); // define their responses to the received data. var defaultReceivedHandler = new EventHandler<DataReceivedEventArgs>((sender, e) => { var device = sender as Device; Console.WriteLine("Data received from {0} to {1}.", e.SourceDevice.Name, device.Name); }); d1.DataReceived += defaultReceivedHandler; d2.DataReceived += defaultReceivedHandler; // test send a large bulk of data d1.Send(d2, new byte[20 << 10], true, () => { Console.WriteLine("Data sent complete from D1 to D2"); }); Console.WriteLine("Block point reached."); // perform another round var d3 = new Device { Name = "D3" }; simulator.Register(d3, new int[] { d1.ID, d2.ID }); d3.DataReceived += defaultReceivedHandler; d3.Send(d2, new byte[20 << 10], false, () => { Console.WriteLine("Data sent complete from D3 to D2"); }); d3.Send(d1, new byte[20 << 10], true, () => { Console.WriteLine("Data sent complete from D3 to D1"); }); // d1 leaves the network, and then try to send it some data simulator.Leave(d1); try { d3.Send(d1, new byte[10]); } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Error: " + e.Message); Console.ForegroundColor = ConsoleColor.Gray; } Application.Run(); }
/// <summary> /// Sends the specified data to the target device. /// </summary> /// <param name="target">The target device.</param> /// <param name="data">The data.</param> /// <param name="callback">The callback which will be invoked when data sending is finished.</param> public void Send(Device target, byte[] data, bool isBlocked = false, Action callback = null) { if (isBlocked) { var e = new AutoResetEvent(false); Simulator.Send(this, target, data, () => { if (callback != null) callback(); e.Set(); }, TriggerDataReceivedEvent); e.WaitOne(); } else { Simulator.Send(this, target, data, callback, TriggerDataReceivedEvent); } }
/// <summary> /// Registers the specified device in the network. /// </summary> /// <param name="d">The d.</param> /// <param name="connectedIds">The connected ids.</param> /// <returns>Assigned ID to the device</returns> public void Register(Device d, int[] connectedIds) { devices.Add(d); activeIds.Add(nextId); d.ID = nextId; d.Simulator = this; AdjacentList.Add(nextId, new List<int>()); if (connectedIds != null) foreach (var id in connectedIds) Connect(nextId, id); ++nextId; }
/// <summary> /// Sends the specified data from a device to another. /// </summary> /// <param name="from">The device from which the data is sent.</param> /// <param name="to">The target device</param> /// <param name="data">The data.</param> /// <remarks> /// This function also force the network speed limit. Currently the limit is put /// in the capability of receiving data for every device. /// </remarks> public void Send(Device from, Device to, byte[] data, Action callback, EventHandler<DataReceivedEventArgs> dataReceivedTrigger) { // check whether the two devices are connected. if (!AdjacentList[from.ID].Contains(to.ID)) throw new Exception("The two devices are not connected."); // prepare for the buffer,callback queue, and sourceDevice queue if (!dataToSend.ContainsKey(to.ID)) dataToSend.Add(to.ID, new Queue<Queue<byte>>()); dataToSend[to.ID].Enqueue(new Queue<byte>(data)); if (!callbacks.ContainsKey(to.ID)) callbacks.Add(to.ID, new Queue<Action>()); callbacks[to.ID].Enqueue(callback); if (!sourceDevices.ContainsKey(to.ID)) sourceDevices.Add(to.ID, new Queue<Device>()); sourceDevices[to.ID].Enqueue(from); // Set a time to trigger the data received events. if (sendingIds.Contains(to.ID)) return; sendingIds.Add(to.ID); var timer = new System.Timers.Timer(this.SimulationInterval) { AutoReset = true }; timer.Elapsed += (sender, e) => { // use closure to access the target device var queue = dataToSend[to.ID].Peek(); var buffer = new byte[Math.Min(this.MaxNetworkSpeed, queue.Count)]; for (int i = 0; i < buffer.Length; i++) buffer[i] = queue.Dequeue(); // trigger the event var sourceDevice = sourceDevices[to.ID].Peek(); dataReceivedTrigger(to, new DataReceivedEventArgs() { SourceDevice = sourceDevice, Data = buffer }); // dispose the timer when all the data is sent. if (queue.Count == 0) { if (dataToSend[to.ID].Count == 0) { timer.Dispose(); sendingIds.Remove(to.ID); } sourceDevices[to.ID].Dequeue(); var toCallBack = callbacks[to.ID].Dequeue(); if (toCallBack != null) toCallBack(); dataToSend[to.ID].Dequeue(); } }; timer.Enabled = true; }
/// <summary> /// Make specified device leave the network. /// </summary> /// <param name="d">The d.</param> public void Leave(Device d) { devices.Remove(d); activeIds.Remove(d.ID); AdjacentList.Remove(d.ID); //Directly disconnect all the neighbors. // note the connections are symmetric. Do another round. foreach (var key in AdjacentList.Keys) if (AdjacentList[key].Contains(d.ID)) AdjacentList[key].Remove(d.ID); }