Robert's blog
Robert Važan

Introducing JuiceStream library

Assorted implementations of .NET's Stream including multiplexing, proper buffering, cancellation, pinging, in-memory streams, and lead streams.

.NET's Stream is a very versatile abstraction. You can define all kinds of streams, layer streams upon streams, and soon you discover reusable Stream implementations that can be plugged in to handle specific behaviors or traits of the stream you are working with. JuiceStream library attempts to include basic Stream implementations. Binary communication protocols are probably the best place to use these classes.

JuiceStream is available from NuGet and licensed under BSD license. There's a dependency on .NET 4.5 due to the heavy use of await/async. Synchronous alternatives to all async methods are also included. After installing JuiceStream, you will gain access to the following Stream implementations:

DuplexBufferedStream - .NET already has its BufferedStream, but that one will throw unexpected exceptions, especially on NetworkStreams. JuiceStream's DuplexBufferedStream embeds two BufferedStream instances, one for each direction, to provide full duplex buffering over non-seekable streams.

MultiplexStream - As we have seen with HTTP, creating lots of parallel connections isn't healthy for performance of your application. Just like HTTP 2.0, JuiceStream's MultiplexStream allows you to tunnel multiple substreams through single outer stream. Either peer can issue Connect calls that create substreams while the other peer issues Accept calls to get the opposite end of the substream.

PingStream - Half-open TCP connections can cause serious sync issues in applications. Default 2-hour TCP keepalive cannot be configured on a per-connection basis on Windows. Common wisdom is to implement application-layer ping. PingStream will spare you of this duty. Designed to work over single substream of MultiplexStream, both endpoints of the PingStream will perform regular pings in order to kill broken connections as early as possible.

QueueStream - Mostly intended for testing, QueueStream is like PipeStream, but it drops the inter-process functionality in favor of easy setup and higher performance. Writes to QueueStream come out as reads from the same QueueStream. DuplexQueueStream embeds two QueueStream instances to provide full-duplex in-memory communication between two linked DuplexQueueStream peers.

PrefixStream - Many protocols need to include short "magic" headers that identify the protocol and its version. PrefixStream encapsulates this behavior. It writes out specified binary prefix before first write and checks presence and correctness of the prefix before first read.

CancellableStream - When writing a lot of async code, one often discovers that all those CancellationToken instances passed around are only used as parameters to Stream methods. CancellableStream spares you of the possibility of forgetting to use the CancellationToken somewhere by enforcing use of specified CancellationToken in all calls to the controlled Stream.

ForceCancelStream - Even though NetworkStream implements Stream methods that take CancellationToken, the supplied token is in fact ignored and NetworkStream keeps hanging on reads even after cancellation has been signaled. ForceCancelStream is a wrapper around NetworkStream (or any other stream) that enforces the use of CancellationToken. It will return immediately after cancellation is signaled. The underlying stream will be left hanging in separate thread that will be cleaned up after you close the stream, which is the most likely scenario after you cancel an operation.

JuiceStream is quite thoroughly unit-tested and I am using it in a production application, but you should be aware that it is all beta code. Please submit your pull requests to JuiceStream. I especially welcome public method documentation, fixes, and optimizations.