A design problem  
Author Message
Nerick





PostPosted: .NET Framework Networking and Communication, A design problem Top

Hello,
I'm currently writing a part of an application which must translate a sequence of bytes (read from a network connection) according to its structure. The whole sequence is considered as a unique value, except for the first 2 bytes which identify the type of the value (numeric, string, or structured), and how the value should be parsed (the value itself can eventually be a list of values).
I was thinking of inheriting from System.IO.BinaryReader for the parser (using a System.IO.MemoryStream for the byte sequence), having an abstract base class for the sequence content representation (class ContentBase), and different concrete classes which inherit from ContentBase (for example ContentInteger, ContentString, ContentListString, etc).
However, I can't figure how to combine those elements to produce the correct instance and then parse the sequence the right way (maybe a known design pattern that I'm missing )... any suggestion would be appreciated :-)
thanks in advance


.NET Development23  
 
 
OmegaMan





PostPosted: .NET Framework Networking and Communication, A design problem Top

I a not quite sure of your intend goal, but I had written a system to broadcast UDP messages which there was a header with clearly defined sections and sizes and of course the following data load.

For the consumer, or reader of the UPD message, I simply translated the items into a string and the created the appropriate objects after reading in the header which told the code the data load size to extract from the subsequent byte array.

Here is a snippet where the byte array is translated and placed into a string, the header which is first read is broken into tokens, there was a special nonprintable character (PI in the code example) as the delimiter which allowed for tokens, and then processing could be done. The first two bytes where an indicator that this message could be read and was processed elsewhere, hence it starts at position 2 in the byte array.


using System.Diagnostics;
using System.IO;
using System.Text;

public bool MessageDecode(byte[] messageToDecode)
{
    bool propermessage = false;

    try
    {
        message = messageToDecode;

        UnicodeEncoding encoding = new UnicodeEncoding( );

        string sizeString = encoding.GetString(message, 2, 128); // Overshoot to pull all the info out.

        string[] tokens = sizeString.Split(PI);

        if (tokens.Length < 7)
            throw new Exception("Unable to extract the appropriate number of tokens from the byte array during decoding. This may not be a BroadcastVector.");

        // Extract the data from predefined areas
       int index = 0;

        Demark = tokens[index++];

        StreamPosition = Int32.Parse(tokens[index++]);

        StreamTotal = Int32.Parse(tokens[index++]);

        SizeData = Int32.Parse(tokens[index++]);

        SizeOriginatingData = Int32.Parse(tokens[index++]);

        SizeGuid = Int32.Parse(tokens[index++]);

        GuidID = tokens[index++];

...

 



 
 
Nerick





PostPosted: .NET Framework Networking and Communication, A design problem Top

I managed to work it out properly by inheriting from the BinaryReader class of the .NET framework (also the endian order for the 16bits and 32bits value types needed to be changed, wich I could do by overriding BinaryReader.ReadInt16 and BinaryReader.ReadInt32).

In the inherited BinaryParser, I added a method for each concrete type to read:
public ContentInteger ReadContentInteger();
public ContentString ReadContentString();
public ContentListString ReadContentListString();
etc.

The thing that looks dirty with this solution is for the astract class:
public Content ReadContent()
{
ContentType id = (ContentType)ReadInt16();
BaseStream.Seek(StreamPosition.Current, -2);
switch (id)
{
case ContentType.Integer:
return ReadContentInteger();
case ContentType.String:
return ReadContentString();
case ContentType.ListString:
return ReadContentListString();
[...]
}
}

but as a temporary solution I guess it could do (even if it's ugly)
thanks for the sample :-)

 
 
OmegaMan





PostPosted: .NET Framework Networking and Communication, A design problem Top

I am glad that you have found a system to work with...there are more than one way to skin a cat. If this works and there is not obvious answer or solution...then it is the best way.

As long as ends justifies the means.


 
 
RizwanSharp





PostPosted: .NET Framework Networking and Communication, A design problem Top

The simplest solution is to create a class MyMessage and mark it with Serializable attribute,

Here:

[Serializable]

class MyMessage

{

// Put all your Data here

}

Serialize this class to MemoryStream,

Send the bytes of MemoryStream to the NetWorkStream.........

On The other Side, Get those bytes and Reconstruct the Message from the bytes using Deserialization,

See, this Namespace:

System.Runtime.Serialization.*........

And Specifically see BinaryFormatter class...

Make sure to Seperate the logic of Serialization/Deserialization in a single seperate dll.. And use it on both side,, Client and Server to work fine. Otherwise you'll get AssemblyNotFound Exception or something like that.

If you need any more detail or help, Feel Free to Write Again.

Best Regards,

Rizwan