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); }
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); }
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); }
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); }
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); } }
public void OpenClose() { DynamicStream aDynamicStream = new DynamicStream(); aDynamicStream.Close(); }
/// <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); } } } }