static void Main(string[] args) { int size = 900 * 720 * 2; string name = "SharedMemoryTest"; data = new byte[size]; var buf = new SharedMemory.CircularBuffer(name); bufW = new SharedMemory.CircularBuffer(name + "W"); int i = 0; Task.Factory.StartNew(Read); while (true) { data[0] = (byte)Console.ReadKey().Key; int result = buf.Write(data); _Signal.WaitOne(); Console.WriteLine("========================" + data[0]); } Console.ReadKey(); }
static void Main(string[] args) { Console.WriteLine("Press <enter> to start client"); Console.ReadLine(); Console.WriteLine("Open existing shared memory circular buffer"); using (SharedMemory.CircularBuffer theClient = new SharedMemory.CircularBuffer("TEST")) { Console.WriteLine("Buffer {0} opened, NodeBufferSize: {1}, NodeCount: {2}", theClient.Name, theClient.NodeBufferSize, theClient.NodeCount); long bufferSize = theClient.NodeBufferSize; byte[] writeDataProof; byte[] writeData = new byte[bufferSize]; List<byte[]> dataList = new List<byte[]>(); // Generate data for integrity check for (var j = 0; j < 256; j++) { var data = new byte[bufferSize]; for (var i = 0; i < data.Length; i++) { data[i] = (byte)((i + j) % 255); } dataList.Add(data); } int skipCount = 0; long iterations = 0; long totalBytes = 0; long lastTick = 0; Stopwatch sw = Stopwatch.StartNew(); int threadCount = 0; Action reader = () => { int myThreadIndex = Interlocked.Increment(ref threadCount); int linesOut = 0; bool finalLine = false; for (; ; ) { int amount = theClient.Read(writeData, 100); //int amount = theClient.Read<byte>(writeData, 100); if (amount == 0) { Interlocked.Increment(ref skipCount); } else { // Only check data integrity for first thread if (threadCount == 1) { bool mismatch = false; writeDataProof = dataList[((int)Interlocked.Read(ref iterations)) % 255]; for (var i = 0; i < writeDataProof.Length; i++) { if (writeData[i] != writeDataProof[i]) { mismatch = true; Console.WriteLine("Buffers don't match!"); break; } } if (mismatch) break; } Interlocked.Add(ref totalBytes, amount); Interlocked.Increment(ref iterations); } if (threadCount == 1 && Interlocked.Read(ref iterations) > 500) finalLine = true; if (myThreadIndex < 3 && (finalLine || sw.ElapsedTicks - lastTick > 1000000)) { lastTick = sw.ElapsedTicks; Console.WriteLine("Read: {0}, Wait: {1}, {2}MB/s", ((double)totalBytes / 1048576.0).ToString("F0"), skipCount, (((totalBytes / 1048576.0) / sw.ElapsedMilliseconds) * 1000).ToString("F2")); linesOut++; if (finalLine || (myThreadIndex > 1 && linesOut > 10)) { Console.WriteLine("Completed."); break; } } } }; Console.WriteLine("Testing data integrity (high CPU, low bandwidth)..."); reader(); Console.WriteLine(""); skipCount = 0; iterations = 0; totalBytes = 0; lastTick = 0; sw.Reset(); sw.Start(); Console.WriteLine("Testing data throughput (low CPU, high bandwidth)..."); #if NET40Plus Task c1 = Task.Factory.StartNew(reader); Task c2 = Task.Factory.StartNew(reader); Task c3 = Task.Factory.StartNew(reader); //Task c4 = Task.Factory.StartNew(reader); #else ThreadPool.QueueUserWorkItem((o) => { reader(); }); ThreadPool.QueueUserWorkItem((o) => { reader(); }); ThreadPool.QueueUserWorkItem((o) => { reader(); }); #endif Console.ReadLine(); } }
static void Main(string[] args) { Console.WriteLine("Press <enter> to start client"); Console.ReadLine(); Console.WriteLine("Open existing shared memory circular buffer"); using (SharedMemory.CircularBuffer theClient = new SharedMemory.CircularBuffer("TEST")) { Console.WriteLine("Buffer {0} opened, NodeBufferSize: {1}, NodeCount: {2}", theClient.Name, theClient.NodeBufferSize, theClient.NodeCount); long bufferSize = theClient.NodeBufferSize; byte[] writeDataProof; byte[] writeData = new byte[bufferSize]; List <byte[]> dataList = new List <byte[]>(); // Generate data for integrity check for (var j = 0; j < 256; j++) { var data = new byte[bufferSize]; for (var i = 0; i < data.Length; i++) { data[i] = (byte)((i + j) % 255); } dataList.Add(data); } int skipCount = 0; long iterations = 0; long totalBytes = 0; long lastTick = 0; Stopwatch sw = Stopwatch.StartNew(); int threadCount = 0; Action reader = () => { int myThreadIndex = Interlocked.Increment(ref threadCount); int linesOut = 0; bool finalLine = false; for (; ;) { int amount = theClient.Read(writeData, 100); //int amount = theClient.Read<byte>(writeData, 100); if (amount == 0) { Interlocked.Increment(ref skipCount); } else { // Only check data integrity for first thread if (threadCount == 1) { bool mismatch = false; writeDataProof = dataList[((int)Interlocked.Read(ref iterations)) % 255]; for (var i = 0; i < writeDataProof.Length; i++) { if (writeData[i] != writeDataProof[i]) { mismatch = true; Console.WriteLine("Buffers don't match!"); break; } } if (mismatch) { break; } } Interlocked.Add(ref totalBytes, amount); Interlocked.Increment(ref iterations); } if (threadCount == 1 && Interlocked.Read(ref iterations) > 500) { finalLine = true; } if (myThreadIndex < 3 && (finalLine || sw.ElapsedTicks - lastTick > 1000000)) { lastTick = sw.ElapsedTicks; Console.WriteLine("Read: {0}, Wait: {1}, {2}MB/s", ((double)totalBytes / 1048576.0).ToString("F0"), skipCount, (((totalBytes / 1048576.0) / sw.ElapsedMilliseconds) * 1000).ToString("F2")); linesOut++; if (finalLine || (myThreadIndex > 1 && linesOut > 10)) { Console.WriteLine("Completed."); break; } } } }; Console.WriteLine("Testing data integrity (high CPU, low bandwidth)..."); reader(); Console.WriteLine(""); skipCount = 0; iterations = 0; totalBytes = 0; lastTick = 0; sw.Reset(); sw.Start(); Console.WriteLine("Testing data throughput (low CPU, high bandwidth)..."); #if NET40Plus Task c1 = Task.Factory.StartNew(reader); Task c2 = Task.Factory.StartNew(reader); Task c3 = Task.Factory.StartNew(reader); //Task c4 = Task.Factory.StartNew(reader); #else ThreadPool.QueueUserWorkItem((o) => { reader(); }); ThreadPool.QueueUserWorkItem((o) => { reader(); }); ThreadPool.QueueUserWorkItem((o) => { reader(); }); #endif Console.ReadLine(); } }
/// <summary> /// Construct a new RpcBuffer /// </summary> /// <param name="name">The unique channel name. This is the name to be shared between the master/slave pair. Each pair must have a unique value.</param> /// <param name="bufferCapacity">Master only: Maximum buffer capacity. Messages will be split into packets that fit this capacity (including a packet header of 64-bytes). The slave will use the same size as defined by the master</param> /// <param name="protocolVersion">ProtocolVersion.V1 = 64-byte header for each packet</param> /// <param name="bufferNodeCount">Master only: The number of nodes in the underlying circular buffers, each with a size of <paramref name="bufferCapacity"/></param> public RpcBuffer(string name, int bufferCapacity = 50000, RpcProtocol protocolVersion = RpcProtocol.V1, int bufferNodeCount = 10) { if (bufferCapacity < 256) // min 256 bytes { throw new ArgumentOutOfRangeException(nameof(bufferCapacity), "cannot be less than 256 bytes"); } if (bufferCapacity > 1024 * 1024) // max 1MB { throw new ArgumentOutOfRangeException(nameof(bufferCapacity), "cannot be larger than 1MB"); } Statistics = new RpcStatistics(); masterMutex = new Mutex(true, name + "SharedMemory_MasterMutex", out bool createdNew); if (createdNew && masterMutex.WaitOne(500)) { instanceType = InstanceType.Master; } else { instanceType = InstanceType.Slave; if (masterMutex != null) { masterMutex.Close(); masterMutex.Dispose(); masterMutex = null; } } switch (protocolVersion) { case RpcProtocol.V1: this.protocolVersion = protocolVersion; protocolLength = FastStructure.SizeOf <RpcProtocolHeaderV1>(); Statistics.ProtocolOverheadPerPacket = protocolLength; break; } this.bufferCapacity = bufferCapacity; this.bufferNodeCount = bufferNodeCount; if (instanceType == InstanceType.Master) { WriteBuffer = new CircularBuffer(name + "_Slave_SharedMemory_MMF", bufferNodeCount, this.bufferCapacity); ReadBuffer = new CircularBuffer(name + "_Master_SharedMemory_MMF", bufferNodeCount, this.bufferCapacity); } else { ReadBuffer = new CircularBuffer(name + "_Slave_SharedMemory_MMF"); WriteBuffer = new CircularBuffer(name + "_Master_SharedMemory_MMF"); this.bufferCapacity = ReadBuffer.NodeBufferSize; this.bufferNodeCount = ReadBuffer.NodeCount; } this.msgBufferLength = Convert.ToInt32(this.bufferCapacity) - protocolLength; Task.Run(() => { switch (protocolVersion) { case RpcProtocol.V1: ReadThreadV1(); break; } }); }
public static void StartPacketReaderMMF() { int nodeBufferSize = sizeof(byte) * _pktMmfBufferSize; SharedMemory.CircularBuffer packetMMF; if (!CheckMMFileExists(_pktMmfName)) { packetMMF = new SharedMemory.CircularBuffer(_pktMmfName, _pktMmfNodeCount, nodeBufferSize); } else { packetMMF = new SharedMemory.CircularBuffer(_pktMmfName); } byte[] writtenData = new byte[_pktMmfBufferSize]; //int threadCount = 0; Action reader = () => { //int myThreadIndex = Interlocked.Increment(ref threadCount); //Output.outMsgBox("Started thread {0}: ", threadCount); for (; ;) { //var t1 = Environment.TickCount; Debug.WriteLine("packetMMF.Read(writtenData) {0}", ID); //var t2 = Environment.TickCount; if (t2-t1 > 0) Debug.WriteLine("ANTES de packetMMF.Read {0} - diff: {1}", ID, t2-t1); //The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. int amount = packetMMF.Read(writtenData, 0, -1); //var t3 = Environment.TickCount; if (t3 - t2 > 0) Debug.WriteLine("DESPUES de server.Read {0} - diff: {1}", ID, t3 - t2); if (amount == 0) { throw new Exception("Read 0 bytes from queue!"); } Output.outString("Read data: {0}", BitConverter.ToString(writtenData)); // PacketInfo HEADER var packetInfo = new PacketInfo(); var piSize = Marshal.SizeOf(packetInfo); var piData = new byte[piSize]; // Reads the piSize bytes corresponding to the packetInfo Buffer.BlockCopy(writtenData, 0, piData, 0, piSize); // Converts the bytes to a packetInfo IntPtr ptr = Marshal.AllocHGlobal(piSize); Marshal.Copy(piData, 0, ptr, piSize); packetInfo = (PacketInfo)Marshal.PtrToStructure(ptr, packetInfo.GetType()); var cSize = packetInfo.Size; var cData = new byte[cSize]; // Packet size can not be bigger than buffer size Debug.Assert(cSize < _pktMmfBufferSize); Buffer.BlockCopy(writtenData, piSize, cData, 0, cSize); PacketManager.PacketReceived(packetInfo, ref cData); //var t4 = Environment.TickCount; if (t4- t3 > 0) Debug.WriteLine("DESPUES de PacketManager.PacketReceived {0} - diff: {1}", ID, t4 - t3); } }; // Start reader thread ThreadPool.QueueUserWorkItem(o => { reader(); }); }
public static void WriteCommandToCmdMMF(ServerCodes sc, byte[] data = null, UInt16 newLength = 0, ushort socketId = 0) { int mmfWriteTimeout = 1000; byte[] writtenData; if (sc == ServerCodes.SCODE_INJECTPACKET) { /* | ServerCode | SocketID | newLength | Packet | | 1-byte | 2-bytes | 2-bytes |--------------- data -------------| |------------------------------------ writtenData --------------------------------------| */ writtenData = new byte[1 + 2 + 2 + newLength]; writtenData[0] = (byte)sc; Array.Copy(FilterManager.StructToBytes(socketId), 0, writtenData, 1, 2); Array.Copy(FilterManager.StructToBytes(newLength), 0, writtenData, 3, 2); Array.Copy(data, 0, writtenData, 5, newLength); } else if (sc == ServerCodes.SCODE_STARTFILTERING) { /* | ServerCode | FilterCount | Filter Data | | 1-byte | 1-byte |-----------------Data------------------------| |------------------------ writtenData ---------------------------------------| */ writtenData = new byte[FilterManager.FILTERINBYTESSIZE * FilterManager.GetActiveFilterCount() + 2]; // Minimo: SizeOf(Filter) * cantActivos + 2 writtenData[0] = (byte)sc; writtenData[1] = (byte)FilterManager.GetActiveFilterCount(); byte[] bytes = FilterManager.ConvertFilterListToBytes(); Array.Copy(bytes, 0, writtenData, 2, FilterManager.FILTERINBYTESSIZE * FilterManager.GetActiveFilterCount()); } else if (sc == ServerCodes.SCODE_SETPACKET) { /* | ServerCode | newLength | Packet Data | | 1-byte | 2-bytes |-----------------Data-----------------------------| |------------------------------------- writtenData ----------------------------| */ writtenData = new byte[1 + 2 + newLength]; writtenData[0] = (byte)sc; Array.Copy(FilterManager.StructToBytes(newLength), 0, writtenData, 1, 2); Array.Copy(data, 0, writtenData, 3, newLength); } else if (sc == ServerCodes.SCODE_LOADDLLEX) { /* | ServerCode | fileName string | | 1-byte |---------- string.Length --------| |------------------- writtenData --------------| */ writtenData = new byte[1 + Settings.DLLEx.Length]; writtenData[0] = (byte)sc; Array.Copy(Encoding.ASCII.GetBytes(Settings.DLLEx), 0, writtenData, 1, Settings.DLLEx.Length); } else if (sc == ServerCodes.SCODE_STARTCAPTURE || sc == ServerCodes.SCODE_STOPCAPTURE || sc == ServerCodes.SCODE_STOPFILTERING || sc == ServerCodes.SCODE_UNLOADDLLEX) { writtenData = new byte[1]; writtenData[0] = (byte)sc; } else { throw new NotImplementedException("ServerCode " + (int)sc + " NOT IMPLEMENTED"); } // Spawneamos un thread que puede esperar el mmfWriteTimeout para escribir el comando //int threadCount = 0; //int myThreadIndex = Interlocked.Increment(ref threadCount); if (CheckMMFileExists(_cmdMmfName)) { cmdMMF = new SharedMemory.CircularBuffer(_cmdMmfName); } else { System.Windows.Forms.MessageBox.Show("ERROR, MMF does not exists!"); // No esta el archivo return; } //The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. int amount = cmdMMF.Write(writtenData, 0, mmfWriteTimeout); if (amount == 0) { throw new Exception("Write 0 bytes to command MMF!"); } //Output.outString("Write data: {0}", BitConverter.ToString(writtenData)); }