Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[C#] Object Serializing and some Networking

Initiate Mage
Joined
Aug 5, 2008
Messages
25
Reaction score
3
This is a simple serializing, de serializing objects tutorial, i think this tutorial will give you a bit of a good start on understanding serializing and experimenting with data transfers, there are several great libraries out there like protobuf NET.

The reason i am writing this very simple thing is because when i remember my self several years ago trying to understand how things work, i always found extremely thorough and complex examples and tutorials, i personally belong to a group of people who like straight to the point things, i prefer reading small tutorials of everything and then just connecting the knowledge from each tutorial.

NOTE: READ THE COMMENTS IN THE CODE

Step 1: Understanding the basics!!

Our serializing class, serializer.cs (you can remove the singleton pattern if you wish)

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace Example
{
    public class Serializer
    {
        //our thread safe singleton implementation
        private static object synching = new Object();

        private static Serializer instance;
        private Serializer() { }
        public static Serializer Instance
        {
            get
            {
                if (instance == null) {
                    //locks the instance
                    lock (synching)
                    {
                        if (instance == null) { instance = new Serializer(); }
                    }
                }
                return instance;
            }
        }

        

        public String serialize(Object obj)
        {
            /* our binary formatter ([URL="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx"]Check this[/URL]) and memory stream ([URL="http://msdn.microsoft.com/en-us/library/system.io.memorystream.aspx"]Check this[/URL]) objects */

            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream memStr = new MemoryStream();
            try {
                bf.Serialize(memStr, obj);
                //now the memorystream has the binary formated object every time we write something into the stream the stream is positioned at the end so that we can continue writing/appending more data to the stream so we have to put it to the starting position that is 0
                memStr.Position = 0;
                //we convert it to array and return it as a base64string
                return Convert.ToBase64String(memStr.ToArray());
            }
            // the memStr will be closed regardless of what happens in the try statement
            finally {
                memStr.Close();
            }
        }


        public Object deSerialize(String str)
        {
            Object obj = new Object();
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream memStr = new MemoryStream(Convert.FromBase64String(str));
            try {
                obj = bf.Deserialize(memStr);
                return obj;
            }
            finally {
                memStr.Close();
            }
        }

    }
}


Our packets.cs, we use Structs over classes here because in general structs consume less heap memory, but its ultimately up to you. Performance is always subjective on what you want to achieve, you can try both structs and classes and benchmark them.


Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace Example
{

        //just a normal enum
        public enum ProtocolWhatEverTypes {  protocol1=1, protocol2=2, protocol3=3  }

        //the struct has to be tagged as Serializable!
        [Serializable]
        public struct Request
        {
            public String id;
            public ProtocolWhatEverTypes protocol;

            public Request(String _id, ProtocolWhatEverTypes _protocol)
            {
                id = _id;
                protocol = _protocol;
            }
        }
    
}


Now you can compile it as a dll for example and distribute it with both the client and the server applications.


TestConsoleApp.cs - Just a console app that tests our DLL ;-), what it does is writing a .bin file in our currently working directory with our serialized object and then read it and output the de serialized data. Don't forget to compile our previous example as a class library "Example.dll" then add reference in our TestConsoleApp Project

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using Example;

namespace ConsoleApplication_Serializing
{
    class TestConsoleApp
    {

        static void Main(string[] args)
        {
            Console.WriteLine("CHOOSE PROTOCOL 1, 2 ,3 (if you type anything else the protocol will by default 3): ");

            ProtocolWhatEverTypes protocol;
            
            String readLineProtocol = Console.ReadLine();
            if (readLineProtocol == "1")
            {
                protocol = ProtocolWhatEverTypes.protocol1;
            }
            else if (readLineProtocol == "2")
            {
                protocol = ProtocolWhatEverTypes.protocol2;
            }
            else 
            {
                protocol = ProtocolWhatEverTypes.protocol3;
            }

            Console.WriteLine("\n\nWRITE ANYTHING: ");

            Request testRequest = new Request( Console.ReadLine(), protocol);


            String serializedStr = Serializer.Instance.serialize( testRequest );
            Console.WriteLine(" \n\n\n\n SERIALIZED: " + serializedStr + "\n\n\n" );
            Write(serializedStr);

            Object deserializedTest = Serializer.Instance.deSerialize(Read());
            Request testRequest_new = (Request) deserializedTest;
            

            Console.WriteLine("DESERIALIZED: " + testRequest_new.id.ToString() + " Protocol: " + testRequest_new.protocol.ToString());


            while (true)
            {
                Thread.Sleep(500);
            }


        }


        public static void Write(String data)
        {
            TextWriter tw = new StreamWriter( Directory.GetCurrentDirectory() + "//test_object_serialize.bin");
            tw.WriteLine(data);
            tw.Close();
        }


        public static String Read()
        {
            String str;
            TextReader tr = new StreamReader( Directory.GetCurrentDirectory() + "//test_object_serialize.bin");
            str = tr.ReadToEnd();
            tr.Close();
            return str;
        }


    }
}


Step 2: Going a bit deeper!!

To be continued! I will be giving some examples with sockets, serializing and encryption here and maybe some multi threading, hopefully tomorrow
 
Experienced Elementalist
Joined
Aug 28, 2012
Messages
214
Reaction score
137
Thanks, I now understand how C# works a little bit better.

I hope this helps others, as it has helped me. :)
 
Back
Top