예제 #1
0
        /// <summary>
        /// Whaiting for previous package receiving by client.
        /// </summary>
        /// <param name="stream">Stream to client.</param>
        /// <param name="mode">Mode of stram managing.</param>
        /// <returns></returns>
        public static bool WaitPackageReceiving(Stream stream, StreamChanelMode mode)
        {
            switch (mode)
            {
            case StreamChanelMode.Oneway:
                Thread.SpinWait(OneWaySpinsPause);
                break;

            case StreamChanelMode.Duplex:
                // Open stream reader.
                BinaryReader sr = new BinaryReader(stream);

                byte[] header = new byte[HEADER_SIZE]; // Bufer that would contain stream header.
                int    blockIndex;                     // Buffer that would contain current stream block.

                #region Wait new package
                // Wait data flush.
                while (true)
                {
                    lock (stream)
                    {
                        // Compute current index block.
                        sr.BaseStream.Position = 0;
                        sr.Read(header, 0, HEADER_SIZE);
                    }
                    blockIndex = BitConverter.ToInt32(header, 0);

                    // Drop if next block request.
                    if (blockIndex == -1)
                    {
                        break;
                    }

                    // Wait.
                    Thread.Sleep(5);
                }
                #endregion
                break;
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Informing server about receiving message by client.
        /// </summary>
        /// <param name="mode">Server mode that decide reaction.</param>
        /// <param name="stream">Target to server stream.</param>
        public static void InformAboutReceving(StreamChanelMode mode, Stream stream)
        {
            lock (stream)
            {
                // Inform server that data recevied.
                if (mode == StreamChanelMode.Duplex)
                {
                    stream.Position = 0;

                    // Build answer.
                    byte[] binaryData = new byte[4];

                    // Add next index as query.
                    Array.Copy(BitConverter.GetBytes(-1), 0, binaryData, 0, 4);

                    // Send data.
                    stream.Write(binaryData, 0, 4);
                    stream.Flush();
                    Thread.Sleep(5);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Writing asynchronicly binary data to stream.
        /// </summary>
        /// <param name="stream">Target stream.</param>
        /// <param name="mode">
        /// Defines mode of package building.
        /// In case of Duplex streaming would droped if @MilisecondsBeforeDrop timeout passed without client's confirmation.
        /// </param>
        /// <param name="data">Binary data that would be sent to stream.</param>
        /// <param name="dataBlockSize">Size of block in bytes that would be send to stream per each flush.</param>
        /// <returns>Asynchronous operation of data writing.</returns>
        public static async Task StreamWriterAsync(Stream stream, StreamChanelMode mode, byte[] data, int dataBlockSize = 610000)
        {
            await Task.Yield();

            // Open stream writer.
            BinaryWriter sw = new BinaryWriter(stream);

            // Send data size.
            lock (stream)
            {
                // Start writing from 0.
                sw.BaseStream.Position = 0;

                // Get binary data.
                byte[] binaryData = new byte[12];

                // Set data length to header.
                Array.Copy(BitConverter.GetBytes(data.Length), 0, binaryData, 0, 4);

                // Set data length to header.
                Array.Copy(BitConverter.GetBytes(dataBlockSize), 0, binaryData, 4, 4);

                // Set data length to header.
                Array.Copy(BitConverter.GetBytes((int)mode), 0, binaryData, 8, 4);

                // Add data to package.
                BuildPackage(0, 0, HEADER_SIZE + 12, binaryData, out byte[] sharedData);

                // Sending data.
                sw.BaseStream.Write(sharedData, 0, sharedData.Length);
                sw.BaseStream.Flush();
            }

            // Wait before sending next package.
            WaitPackageReceiving(stream, mode);

            // Compute count of packages.
            int packagesCount = ComputeRequiredPackages(dataBlockSize, data.Length);

            for (int orderIndex = 0; orderIndex < packagesCount; orderIndex++)
            {
                int packageIndex = orderIndex + 1;
                lock (stream)
                {
                    // Start writing from 0.
                    sw.BaseStream.Position = 0;

                    // Building package.
                    BuildPackage(orderIndex, packageIndex, dataBlockSize, data, out byte[] package);

                    // Sending package to stream.
                    sw.BaseStream.Write(package, 0, package.Length);

                    // Release data to underlaying device.
                    sw.BaseStream.Flush();
                }

                // Wait before sending next package.
                WaitPackageReceiving(stream, mode);
            }

            // Releasing unmanaged memory.
            sw.Dispose();
        }