/// <summary> /// Reads data from the stream. /// </summary> /// <param name="buffer">Buffer to read into.</param> /// <param name="offset">Offset into the buffer where we're to read.</param> /// <param name="count">Number of bytes to read.</param> /// <returns>Number of bytes we read.</returns> public override int Read(byte[] buffer, int offset, int count) { try { if (recvDataCache == null) { recvDataCache = streamSocket.Receive(); } if (!recvDataCache.IsReadable()) { recvDataCache.Release(); recvDataCache = null; return(0); } var bytesRemaining = count; while (recvDataCache != null && recvDataCache.IsReadable() && bytesRemaining > 0) { var bytesToRead = Math.Min(bytesRemaining, recvDataCache.ReadableBytes); bytesRemaining -= recvDataCache.ReadBytes(buffer, offset + count - bytesRemaining, bytesToRead); if (recvDataCache.IsReadable()) { continue; } recvDataCache.Release(); recvDataCache = null; if (streamSocket.HasData) { recvDataCache = streamSocket.Receive(); } } return(count - bytesRemaining); } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } // some sort of error occurred on the socket call, // set the SocketException as InnerException and throw throw new IOException(string.Format("Unable to read data from the transport connection: {0}.", e.Message), e); } }
/// <summary> /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. /// </summary> /// <returns> /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. /// </returns> public override int ReadByte() { if (recvDataCache == null || !recvDataCache.IsReadable()) { recvDataCache = streamSocket.Receive(); } var v = recvDataCache.ReadByte(); if (recvDataCache.IsReadable()) { return(v); } // Release cache if it is not readable. If we do not reset the cache here, // the cache will be used in next Read() that caused 0 bytes return. recvDataCache.Release(); recvDataCache = null; return(v); }