/// <summary> /// Attempts to read a whole message from fromstream /// </summary> /// <param name="fromstream"></param> /// <returns></returns> public static void ReadStreamToMessageStream(MemoryBuffer fromstream, out ChatMessage message) { message = null; //check that we have at least 4 bytes in the buffer, it contains the length of the message if (fromstream.Length > 4) { byte[] lenbuf = new byte[4]; var peeklen = fromstream.Peek(lenbuf, 0, lenbuf.Length); if (peeklen == 4) { //check that we have the whole message in the buffer var messagelength = BitConverter.ToInt32(lenbuf, 0); if (fromstream.Length >= messagelength + 4) { var messagebuffer = new byte[messagelength]; //clear the length from the buffer fromstream.Read(lenbuf, 0, lenbuf.Length); //read the message from the buffer fromstream.Read(messagebuffer, 0, messagelength); var messagestream = new MemoryStream(messagebuffer, 0, messagelength); message = DecodeMessage(messagestream); } } } }
public void ReadWriteMultiplTest() { MemoryBuffer target = new MemoryBuffer(251); byte[] buffer = new byte[10]; for (byte i = 0; i < buffer.Length; i++) buffer[i] = i; for (byte i = 0; i < 50; i++) { target.Write(buffer, 0, buffer.Length); var tempbuf = new byte[10]; var readcount = target.Read(tempbuf, 0, tempbuf.Length /2); readcount += target.Read(tempbuf, tempbuf.Length / 2, tempbuf.Length / 2); CollectionAssert.AreEqual(buffer, tempbuf, "Input not equal output"); Assert.AreEqual(tempbuf.Length, readcount, "Read count is not write count"); } }
/// <summary> /// Reads a sequence of bytes from the uncompressed stream and removes the bytes read from the buffer /// </summary> public override int Read(byte[] buffer, int offset, int count) { bool locktaken = false; _readbufferlock.Enter(ref locktaken); int readbuflen = _readbuffer.Read(buffer, offset, count); _readbufferlock.Exit(); return(readbuflen); }
/// <summary> /// Reads a stream, prevents blocking streams from interrupting flow /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <returns></returns> public override int Read(byte[] buffer, int offset, int count) { //read available bytes from buffer var locktaken = false; _readbufferlock.Enter(ref locktaken); { if (_readthread == null) { _readthread = new Thread(new ThreadStart(ReadThread)); _readthread.Start(); } var readcount = _readbuffer.Read(buffer, offset, count); _readbufferlock.Exit(); return(readcount); } }
/// <summary> /// Write Thread, responsible for compressing and sending the compressed blocks to the base stream /// </summary> private void WriteThread() { while (true) { //writebuffer is either 16mb or flush requested if (((_writebuffer.Length >= _maxbuffersize) || (_flush)) && (_writebuffer.Length > 0)) { _flush = false; //compress the buffer, but also store the original buffer so later we can decide which one is smaller. MemoryStream compressed = new MemoryStream(); MemoryStream uncompressed = new MemoryStream(); byte[] buffer = new byte[_tempbuffersize]; bool locktaken = false; _writebufferlock.Enter(ref locktaken); int readbytes = 0; do { readbytes = _writebuffer.Read(buffer, 0, buffer.Length); uncompressed.Write(buffer, 0, readbytes); } while (readbytes > 0); _writebufferlock.Exit(); //compress the block uncompressed.Seek(0, SeekOrigin.Begin); using (GZipStream gzcompression = new GZipStream(compressed, CompressionMode.Compress, true)) { uncompressed.CopyTo(gzcompression); gzcompression.Close(); } //check if we rather use the compressed or the uncompressed byte stream MemoryStream selectedstream = null; //check if compressed buffer is bigger than uncompressed buffer. if (compressed.Length > uncompressed.Length) { selectedstream = uncompressed; } else { selectedstream = compressed; } //write to writecompressed //first, write 3 bytes of the length, so later the reading stream can determine the block size. byte[] lenint = BitConverter.GetBytes((int)selectedstream.Length); _basestream.Write(lenint, 0, 3); //write which stream we selected, either the compressed or the uncompressed. if (compressed.Length > uncompressed.Length) { _basestream.WriteByte(0); } else { _basestream.WriteByte(1); } //write writecompressed to underlying stream selectedstream.Seek(0, SeekOrigin.Begin); do { readbytes = selectedstream.Read(buffer, 0, buffer.Length); _basestream.Write(buffer, 0, readbytes); } while (readbytes > 0); _basestream.Flush(); } else { Thread.Sleep(1); } } }