예제 #1
0
        public void WriteRead()
        {
            DynamicStream aDynamicStream = new DynamicStream();

            BinaryWriter aBinaryWriter = new BinaryWriter(aDynamicStream);

            aBinaryWriter.Write("Hello");
            aBinaryWriter.Write((int)123);

            BinaryReader aBinaryReader = new BinaryReader(aDynamicStream);
            string       aString       = aBinaryReader.ReadString();
            int          aNumber       = aBinaryReader.ReadInt32();

            Assert.AreEqual("Hello", aString);
            Assert.AreEqual(123, aNumber);
        }
예제 #2
0
        public void UnblockReadingByClosing()
        {
            DynamicStream aDynamicStream = new DynamicStream();

            Action aClosing = () =>
            {
                Thread.Sleep(500);
                aDynamicStream.Close();
            };


            // Close the stream in another thread in 500 ms.
            aClosing.BeginInvoke(null, null);

            // Start to read in this thread. The reading will be blocked until the stream is closed.
            int aReadSize = aDynamicStream.ReadByte();

            Assert.AreEqual(-1, aReadSize);
        }
예제 #3
0
        public void WriteFragmentsReadWholeMultithread()
        {
            DynamicStream aDynamicStream = new DynamicStream();

            string aString  = "";
            Action aReading = () =>
            {
                BinaryReader aBinaryReader = new BinaryReader(aDynamicStream);
                aString = aBinaryReader.ReadString();
            };

            Action aWriting = () =>
            {
                Thread.Sleep(100);

                // Convert the string to bytes.
                MemoryStream aMemoryStream = new MemoryStream();
                BinaryWriter aBinaryWriter = new BinaryWriter(aMemoryStream);
                aBinaryWriter.Write("Hello_12345678901234567890_1234567890");

                byte[] aData = aMemoryStream.ToArray();

                // Put it byte by byte to the tested stream.
                foreach (byte b in aData)
                {
                    aDynamicStream.WriteByte(b);
                }
            };


            // Invoke "slow" writing in another thread
            aWriting.BeginInvoke(null, null);

            // Invoke "fast" reading in this thread
            // This thread should be blocked until all messages are read.
            aReading.Invoke();

            Assert.AreEqual("Hello_12345678901234567890_1234567890", aString);
        }
예제 #4
0
        public void WriteRead_1000000()
        {
            byte[] aData = new byte[500];

            DynamicStream aDynamicStream = new DynamicStream();

            Stopwatch aStopWatch = new Stopwatch();

            aStopWatch.Start();

            for (int i = 0; i < 1000000; ++i)
            {
                aDynamicStream.Write(aData, 0, aData.Length);
            }

            for (int i = 0; i < 1000000; ++i)
            {
                aDynamicStream.Read(aData, 0, aData.Length);
            }

            aStopWatch.Stop();
            Console.WriteLine("Elapsed time: {0}", aStopWatch.Elapsed);
        }
예제 #5
0
        public void WriteReadMultithread()
        {
            DynamicStream aDynamicStream = new DynamicStream();

            string aString  = "";
            int    aNumber  = 0;
            Action aReading = () =>
            {
                BinaryReader aBinaryReader = new BinaryReader(aDynamicStream);
                aString = aBinaryReader.ReadString();
                aNumber = aBinaryReader.ReadInt32();
            };

            Action aWriting = () =>
            {
                Thread.Sleep(100);

                BinaryWriter aBinaryWriter = new BinaryWriter(aDynamicStream);
                aBinaryWriter.Write("Hello");

                Thread.Sleep(300);

                aBinaryWriter.Write((int)123);
            };


            // Invoke "slow" writing in another thread
            aWriting.BeginInvoke(null, null);

            // Invoke "fast" reading in this thread
            // This thread should be blocked until all messages are read.
            aReading.Invoke();


            Assert.AreEqual("Hello", aString);
            Assert.AreEqual(123, aNumber);
        }
        public void DoRequestListening()
        {
            using (EneterTrace.Entering())
            {
                myIsListeningToResponses = true;
                ushort aCloseCode = 0;

                try
                {
                    DynamicStream aContinuousMessageStream = null;

                    while (!myStopReceivingRequestedFlag)
                    {
                        // Decode the incoming message.
                        WebSocketFrame aFrame = WebSocketFormatter.DecodeFrame(myClientStream);

                        if (!myStopReceivingRequestedFlag && aFrame != null)
                        {
                            // Frames from server must be unmasked.
                            // According the protocol, If the frame was NOT masked, the server must close connection with the client.
                            if (aFrame.MaskFlag == false)
                            {
                                throw new InvalidOperationException(TracedObject + "received unmasked frame from the client. Frames from client shall be masked.");
                            }

                            // Process the frame.
                            if (aFrame.FrameType == EFrameType.Ping)
                            {
                                // Response 'pong'. The response responses same data as received in the 'ping'.
                                SendFrame(maskingKey => WebSocketFormatter.EncodePongFrame(maskingKey, aFrame.Message));
                            }
                            else if (aFrame.FrameType == EFrameType.Close)
                            {
                                EneterTrace.Debug(TracedObject + "received the close frame.");
                                break;
                            }
                            else if (aFrame.FrameType == EFrameType.Pong)
                            {
                                Notify(PongReceived);
                            }
                            // If a new message starts.
                            else if (aFrame.FrameType == EFrameType.Binary || aFrame.FrameType == EFrameType.Text)
                            {
                                // If a previous message is not finished then the new message is not expected -> protocol error.
                                if (aContinuousMessageStream != null)
                                {
                                    EneterTrace.Warning(TracedObject + "detected unexpected new message. (previous message was not finished)");

                                    // Protocol error close code.
                                    aCloseCode = 1002;
                                    break;
                                }

                                WebSocketMessage aReceivedMessage = null;

                                // If the message does not come in multiple frames then optimize the performance
                                // and use MemoryStream instead of DynamicStream.
                                if (aFrame.IsFinal)
                                {
                                    MemoryStream aMessageStream = new MemoryStream(aFrame.Message);
                                    aReceivedMessage = new WebSocketMessage(aFrame.FrameType == EFrameType.Text, aMessageStream);
                                }
                                else
                                // if the message is split to several frames then use DynamicStream so that writing of incoming
                                // frames and reading of already received data can run in parallel.
                                {
                                    // Create stream where the message data will be writen.
                                    aContinuousMessageStream = new DynamicStream();
                                    aContinuousMessageStream.WriteWithoutCopying(aFrame.Message, 0, aFrame.Message.Length);
                                    aReceivedMessage = new WebSocketMessage(aFrame.FrameType == EFrameType.Text, aContinuousMessageStream);
                                }

                                // Put received message to the queue.
                                myReceivedMessages.EnqueueMessage(aReceivedMessage);
                            }
                            // If a message continues. (I.e. message is split into more fragments.)
                            else if (aFrame.FrameType == EFrameType.Continuation)
                            {
                                // If the message does not exist then continuing frame does not have any sense -> protocol error.
                                if (aContinuousMessageStream == null)
                                {
                                    EneterTrace.Warning(TracedObject + "detected unexpected continuing of a message. (none message was started before)");

                                    // Protocol error close code.
                                    aCloseCode = 1002;
                                    break;
                                }

                                aContinuousMessageStream.WriteWithoutCopying(aFrame.Message, 0, aFrame.Message.Length);

                                // If this is the final frame.
                                if (aFrame.IsFinal)
                                {
                                    aContinuousMessageStream.IsBlockingMode = false;
                                    aContinuousMessageStream = null;
                                }
                            }
                        }

                        // If disconnected
                        if (aFrame == null)// || !myTcpClient.Client.Poll(0, SelectMode.SelectWrite))
                        {
                            //EneterTrace.Warning(TracedObject + "detected the TCP connection is not available. The connection will be closed.");
                            break;
                        }
                    }
                }
                catch (IOException)
                {
                    // Ignore this exception. It is often thrown when the connection was closed.
                    // Do not thrace this because the tracing degradates the performance in this case.
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + ErrorHandler.FailedInListeningLoop, err);
                }

                // If the connection is being closed due to a protocol error.
                if (aCloseCode > 1000)
                {
                    // Try to send the close message.
                    try
                    {
                        byte[] aCloseMessage = WebSocketFormatter.EncodeCloseFrame(null, aCloseCode);
                        myClientStream.Write(aCloseMessage, 0, aCloseMessage.Length);
                    }
                    catch
                    {
                    }
                }

                myIsListeningToResponses = false;

                myReceivedMessages.UnblockProcessingThreads();

                // Notify the listening to messages stoped.
                Notify(ConnectionClosed);
            }
        }
예제 #7
0
        public void OpenClose()
        {
            DynamicStream aDynamicStream = new DynamicStream();

            aDynamicStream.Close();
        }
예제 #8
0
        /// <summary>
        /// Listens to client requests and put them to the queue from where the working thread takes them
        /// and notifies the call-backs the pipe input channel.
        /// </summary>
        private void DoListening()
        {
            using (EneterTrace.Entering())
            {
                try
                {
                    // Reconnect the server pipe in the loop.
                    // If the client is not available the thread will wait forewer on WaitForConnection().
                    // When the listening is stopped then the thread is correctly released.
                    while (!myStopListeningRequestFlag)
                    {
                        myPipeServer.WaitForConnection();

                        DynamicStream aDynamicStream = null;
                        try
                        {
                            aDynamicStream = new DynamicStream();

                            // Start thread for reading received messages.
                            EneterThreadPool.QueueUserWorkItem(() =>
                            {
                                while (!myStopListeningRequestFlag && myPipeServer.IsConnected)
                                {
                                    // Read the whole message.
                                    try
                                    {
                                        myMessageHandler(aDynamicStream);
                                    }
                                    catch (Exception err)
                                    {
                                        EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err);
                                    }
                                }

                                aDynamicStream.Close();
                            });

                            // Write incoming messages to the dynamic stream from where the reading thread will notify them.
                            if (!myStopListeningRequestFlag && myPipeServer.IsConnected)
                            {
                                // Read the whole message.
                                try
                                {
                                    StreamUtil.ReadToEndWithoutCopying(myPipeServer, aDynamicStream);
                                }
                                catch (Exception err)
                                {
                                    EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err);
                                }
                            }
                        }
                        finally
                        {
                            if (aDynamicStream != null)
                            {
                                // Note: Do not close the dynamic stream here!
                                //       There can be data read before the closing and the client can still finish to read them.
                                //aDynamicStream.Close();

                                // Unblock the reading thread that can be waiting for messages.
                                aDynamicStream.IsBlockingMode = false;
                            }
                        }

                        // Disconnect the client.
                        if (!myStopListeningRequestFlag)
                        {
                            myPipeServer.Disconnect();
                        }
                    }
                }
                catch (Exception err)
                {
                    // if the error is not caused by closed communication.
                    if (!myStopListeningRequestFlag)
                    {
                        EneterTrace.Error(TracedObject + ErrorHandler.FailedInListeningLoop, err);
                    }
                }
            }
        }