Looking for something specific?
  Home
Home
Articles
Page Tag-Cloud
  Software
Software Tag-Cloud
Building from Source
Open Source Definition
All Software
  Popular Tags
Legacy
C Plus Plus
Source Code
Class
Cryptography
  Members
Login
Web-Email
Notable Members
  Official
Our Company
Copyright Information
Software EULA
GPL EULA
LGPL Eula
Pre-Release EULA
Privacy Policy
  Support
Make Contact
 
NTDLS.StreamFraming
Downloads   0
User Rating   (Rate)
Last Updated   1/22/2024
License   MIT License
- Download -
View all Releases
Recommended Release
Version   1.2.6
Date   1/22/2024
Status   Stable Stable software is believed to be stable and ready for production use.

This software is open source. You can obtain the latest source code from the GitHub repository or browse the releases for the source code associated with a specific release. If you make any changes which you feel improves this application, please let us know via our Contact Page.

NTDLS.StreamFraming

?? Be sure to check out the NuGet pacakge: https://www.nuget.org/packages/NTDLS.StreamFraming

NTDLS.StreamFraming is a set of extension methods for a Stream (typically TCPIP/NetworkStream) that enables reliable framing, compression, optional encryption, two-way communication and support for asynchronous query/reply. Messages are guaranteed to be received in their entirety and in the order which they were sent.

Sending a notification frame:

Here we are using an established TcpClient connection, getting its stream and then calling WriteNotification() to pacakge the payload "MyMessage" and write it to the stream. As per TCP/IP protocol, this can and will be received fragmented and/or concatenated with other bytes that are sent in the stream... but don't worry thats what NTDLS.StreamFraming is here to solve.

using (var tcpStream = tcpClient.GetStream())
{
    while (tcpClient.Connected)
    {
        string text = $"This is a message that was sent at {DateTime.Now.ToLongTimeString()}.";

        //Assemble a message frame and write it to the stream:
        tcpStream.WriteNotification(new MyMessage(text));

        Thread.Sleep(1000);
    }
    tcpStream.Close();
}

Receiving a notification frame:

Here we are using an established TcpClient connection, getting its stream and then calling ReadAndProcessFrames(). ReadAndProcessFrames will read from the stream and determine if the bytes that are received (if any) are a full frame, only a fragment or a concatenation of multiple packets and fragments. Any full frames will be split, validated, decompressed, deserialized and then the callback "ProcessFrameNotificationCallback" will be called for each valid frame.

var frameBuffer = new FrameBuffer();

using (var tcpStream = _tcpClient.GetStream())
{
    while (_tcpClient.Connected)
    {
        //Read from the stream, assemble the bytes into the original messages and call
        //  the handler for each message that was received.
        if (tcpStream.ReadAndProcessFrames(frameBuffer, ProcessFrameNotificationCallback) == false)
        {
            //If ReadAndProcessFrames() returns false then we have been disconnected.
            break;
        }
    }
    tcpStream.Close();
}

//This is the handler for a frame that was written to the stream with a call to WriteNotification().
//Note that the origianl class is received and we use patter matching to determine what we are receiving.
private void ProcessFrameNotificationCallback(IFrameNotification payload)
{
    //We recevied a message, see if it is of the type "MyMessage".
    if (payload is MyMessage myMessage)
    {
        Console.WriteLine($"Received from server: '{myMessage.Text}'");
    }
}

Sending a query frame:

Here we are using an established TcpClient connection, getting its stream and then calling WriteQuery() to pacakge the payload "MyQuery" and write it to the stream. We will then "wait" asynchronously or the client to receive and reply to the query.

using (var tcpStream = tcpClient.GetStream())
{
    while (tcpClient.Connected)
    {
        tcpStream.WriteQuery<MyQueryReply>(new MyQuery("Hello client!")).ContinueWith((o) =>
            {
                if (o.IsCompletedSuccessfully && o.Result != null)
                {
                    Console.WriteLine($"Received [QueryReply] from client: '{o.Result.Text}')");
                }
            });

        //In this example, we have to call ReadAndProcessFrames() even though we are not
        //  supplying it with any callbacks because it receives the replies from the query
        //  that is sent above and routes them to the correct query task handler.
        if (tcpStream.ReadAndProcessFrames(frameBuffer) == false)
        {
            break; //The client disconnected.
        }

        Thread.Sleep(1000);
    }
    tcpStream.Close();
}

Receiving a query frame and replying:

Here we are using an established TcpClient connection, getting its stream and then calling ReadAndProcessFrames(). ReadAndProcessFrames will read from the stream and determine if the bytes that are received are a full frame. Any full frames will be deserialized and routed to the callbacks "ProcessFrameNotificationCallback" or "ProcessFrameQueryCallback" based on their types. "ProcessFrameNotificationCallback" expects a return value to be of the type specified on the original call to WriteQuery(). The value returned from ProcessFrameQueryCallback will be framed and sent back to the originator and then routed to the appropriate waiting asynchronous task.

var frameBuffer = new FrameBuffer();

using (var tcpStream = _tcpClient.GetStream())
{
    while (_tcpClient.Connected)
    {
        //Read from the stream, assemble the bytes into the original messages and call
        //  the handler for each message that was received.
        if (tcpStream.ReadAndProcessFrames(frameBuffer, ProcessFrameNotificationCallback, ProcessFrameQueryCallback) == false)
        {
            //If ReadAndProcessFrames() returns false then we have been disconnected.
            break;
        }
    }
    tcpStream.Close();
}

//This is the handler for a frame that was written to the stream with a call to WriteNotification().
//Note that the origianl class is received and we use patter matching to determine what we are receiving.
private void ProcessFrameNotificationCallback(IFrameNotification payload)
{
    //We recevied a message, see if it is of the type "MyMessage".
    if (payload is MyMessage myMessage)
    {
        Console.WriteLine($"Received from server: '{myMessage.Text}'");
    }
}

private IFrameQueryReply ProcessFrameQueryCallback(IFrameQuery payload)
{
    //We recevied a message, see if it is of the type "MyQuery", if so reply with the type of MyQueryReply.
    if (payload is MyQuery myQuery)
    {
        Console.WriteLine($"Received [Query] from server: '{myQuery.Text}'");

        return new MyQueryReply("Hello Server!");
    }

    throw new Exception("The query type was unhandled.");
}

Supporting Classes:

These are the payload classes that are used in the examples:

Used in the examples to send a one-way notification

    internal class MyMessage : IFrameNotification
    {
        public string Text { get; set; }

        public MyMessage(string text)
        {
            Text = text;
        }
    }

Used in the examples to send a query that expects a reply:

internal class MyQuery : IFrameQuery
{
    public string Text { get; set; }

    public MyQuery(string text)
    {
        Text = text;
    }
}

Used in the examples to reply to a received query:

internal class MyQueryReply : IFrameQueryReply
{
    public string Text { get; set; }

    public MyQueryReply(string text)
    {
        Text = text;
    }
}

Recent Releases:
 1.2.6    1.2.5    1.2.4    1.2.3    1.2.2    1.2.1    1.2.0    1.1.0    1.0.6  

Tags:
 Framing    Io    Network    Socket    Tcp Ip  

No comments currently exists for this software. Why don't you add one?
First Previous Next Last 

 
Copyright © 2024 NetworkDLS.
All rights reserved.
 
Privacy Policy | Our Company | Contact