NTDLS.StreamFraming Usage
Stream extension methods that give any TCP stream reliable message framing, compression and async query/reply.
NTDLS.StreamFraming
What it is. A set of extension methods for Stream (typically a TCP NetworkStream) that solve the classic byte-stream problem: messages arriving fragmented or concatenated. It adds reliable framing with optional compression and encryption, two-way communication, and asynchronous query/reply - every message is guaranteed to be received in its entirety and in the order sent.
When to reach for it. You are building a custom protocol over raw TCP sockets and do not want to hand-roll length prefixes, reassembly buffers and serialization. Skip it if you can use an existing transport library; this gives you the plumbing pieces rather than a full connection manager.
Getting started
Your payload classes implement one of three interfaces:
internal class MyMessage : IFrameNotification
{
public string Text { get; set; }
public MyMessage(string text)
{
Text = text;
}
}
Sending a fire-and-forget notification is one call on the stream:
using var tcpStream = tcpClient.GetStream();
string text = $"This is a message sent at {DateTime.Now.ToLongTimeString()}";
tcpStream.WriteNotification(new MyMessage(text));
Receiving runs a read loop. ReadAndProcessFrames takes a FrameBuffer, splits out complete frames from whatever bytes arrived, deserializes them, and invokes your callback for each one. It returns false when the peer disconnects:
var frameBuffer = new FrameBuffer();
using var tcpStream = tcpClient.GetStream();
while (tcpClient.Connected)
{
if (tcpStream.ReadAndProcessFrames(frameBuffer, ProcessFrameNotificationCallback) == false)
{
break; // Disconnected.
}
}
private void ProcessFrameNotificationCallback(IFrameNotification payload)
{
if (payload is MyMessage myMessage)
{
Console.WriteLine($"Received: '{myMessage.Text}'");
}
}
For request/reply semantics, send with WriteQuery<TReply> and return a reply from your query callback - the response is routed back to the waiting task automatically:
tcpStream.WriteQuery<MyQueryReply>(new MyQuery("Hello client!"))
.ContinueWith(o =>
{
if (o.IsCompletedSuccessfully && o.Result != null)
{
Console.WriteLine($"Reply: '{o.Result.Text}'");
}
});
NuGet: NTDLS.StreamFraming