How to send a serializable object to an external library through sockets?

I have a simple class library that contains only one type. Now I want to send an instance of this type from the client to the server using sockets. The client and server do not know anything about the SendingObject type, so I need to load the assembly.

[Serializable]
    public class SendingObject : MarshalByRefObject
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public SendingObject() { }

        public SendingObject(string firstname, string lastname)
        {
            FirstName = firstname;
            LastName = lastname;
        }

        public override string ToString()
        {
            return string.Format($"Firstname: {FirstName}. Lastname: {LastName}.");
        }
    }

This is my client code :

   class Program
        {
            static void Main(string[] args)
            {   
                string path = @"path to MyLibrary.dll";
                Assembly library = Assembly.LoadFrom(path);

                Type typeObj = library.GetType("MyLibrary.SendingObject");
                var sob = Activator.CreateInstance(typeObj, new object[] {"Bob", "Smith"});

                try
                {
                    SendAddUserMessageFromSocket(83, sob);
                }
                catch (Exception exc)
                {
                    Console.WriteLine(exc.Message);
                }

                Console.WriteLine("\nTap to continue...");
                Console.ReadKey(true);
            }

            static void SendAddUserMessageFromSocket(int port, object obj)
            {    
                byte[] brr = ObjectToByteArray(obj);

                IPHostEntry ipHost = Dns.GetHostEntry("localhost");
                IPAddress ipAddress = ipHost.AddressList[0];
                IPEndPoint endPoint = new IPEndPoint(ipAddress, port);

                Socket sender = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                sender.Connect(endPoint);

                NetworkStream networkStream = new NetworkStream(sender);

                if (networkStream.CanWrite)
                {
                    networkStream.Write(brr, 0, brr.Length);
                }

                Console.WriteLine("The message was sent.");
            }

            // Convert an object to a byte array
            private static byte[] ObjectToByteArray(Object obj)
            {
                if (obj == null)
                    return null;

                BinaryFormatter bf = new BinaryFormatter();
                MemoryStream ms = new MemoryStream();
                bf.Serialize(ms, obj);

                return ms.ToArray();
            }

            // Convert a byte array to an Object
            private static Object ByteArrayToObject(byte[] arrBytes)
            {
                MemoryStream memStream = new MemoryStream();
                BinaryFormatter binForm = new BinaryFormatter();
                memStream.Write(arrBytes, 0, arrBytes.Length);
                memStream.Seek(0, SeekOrigin.Begin);
                Object obj = (Object)binForm.Deserialize(memStream);

                return obj;
            }
        }

This resulting object will be deserialized on the server side. This is the code for my server.

class Program
    {
        static void Main(string[] args)
        {
            IPHostEntry ipHost = Dns.GetHostEntry("localhost");
            IPAddress ipAddr = ipHost.AddressList[0];
            IPEndPoint endPoint = new IPEndPoint(ipAddr, 83);
            Socket socketListener = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            string path = @"path to MyLibrary.dll";
            Assembly library = Assembly.LoadFrom(path);
            Type typeObj = library.GetType("MyLibrary.SendingObject");

            try
            {
                socketListener.Bind(endPoint);
                socketListener.Listen(10);
                bool isWorkFinished = false;

                while (!isWorkFinished)
                {
                    Socket handler = socketListener.Accept();
                    byte[] bytes = new byte[2064];

                    // Get data from connected socket to buffer
                    int numberOfReceivedBytes = handler.Receive(bytes);

                    byte[] bytesObject = new byte[numberOfReceivedBytes];

                    for (int i = 0; i < numberOfReceivedBytes; i++)
                        bytesObject[i] = bytes[i];

                    object res = ByteArrayToObject(bytesObject);
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }

            Console.WriteLine("\nTap to continue...");
            Console.ReadKey(true);
        }

        // Convert an object to a byte array
        private static byte[] ObjectToByteArray(Object obj)
        {
            if (obj == null)
                return null;

            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);

            return ms.ToArray();
        }

        // Convert a byte array to an Object
        private static Object ByteArrayToObject(byte[] arrBytes)
        {
            MemoryStream memStream = new MemoryStream();
            BinaryFormatter binForm = new BinaryFormatter();
            memStream.Write(arrBytes, 0, arrBytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            Object obj = (Object)binForm.Deserialize(memStream);

            return obj;
        }
    }

My SendingObject can be serialized, but I have an error trying to deserialize it.

The assembly could not be found: "MyLibrary, Version = 1.0.0.0, Culture = Neutral, PublicKeyToken = null".

+4
source share
1

, , .NET, Type, Assembly .. , , . :

// assume this is Me.Serialization.Library.csproj
public class MeSerializer {
    public static byte[] Serialize<T>(T obj){
        // serialization method
    }

    public static T Deserialize<T>(byte[] buffer) {
        // deserialization method
    }
}

(, ) Me.Serialization.Library, :

static void SendAddUserMessageFromSocket(int port, object obj)
{    
    // simple edit :
    string path = @"path to MyLibrary.dll";
    Assembly library = Assembly.LoadFrom(path);

    Type typeObj = library.GetType("MyLibrary.SendingObject")
    MethodInfo method = typeof(Me.Serialization.Library.MeSerializer).GetMethod("Serialize");
    MethodInfo generic = method.MakeGenericMethod(typeObj);
    byte[] brr = (byte[])generic.Invoke(null, obj); // null because it is static

    // remember to add reference to Me.Serialization.Library
    // byte[] brr = Me.Serialization.Library.MeSerializer.Serialize<MyLibrary.SendingObject>(obj);

    IPHostEntry ipHost = Dns.GetHostEntry("localhost");
    IPAddress ipAddress = ipHost.AddressList[0];
    // skipped rest of the code for readability
}

:

// simple edit :
string path = @"path to MyLibrary.dll";
Assembly library = Assembly.LoadFrom(path);

Type typeObj = library.GetType("MyLibrary.SendingObject")
MethodInfo method = typeof(Me.Serialization.Library.MeSerializer).GetMethod("Deserialize");
MethodInfo generic = method.MakeGenericMethod(typeObj);

// remember to add reference to Me.Serialization.Library
while (!isWorkFinished)
{
    Socket handler = socketListener.Accept();
    byte[] bytes = new byte[2064];

    // Get data from connected socket to buffer
    int numberOfReceivedBytes = handler.Receive(bytes);

    byte[] bytesObject = new byte[numberOfReceivedBytes];

    for (int i = 0; i < numberOfReceivedBytes; i++)
        bytesObject[i] = bytes[i];

    object brr = (object)generic.Invoke(null, bytesObject);
    // object res = (object)Me.Serialization.Library.MeSerializer.Deserialize<MeLibrary.SendingObject>(bytesObject);
}
0

Source: https://habr.com/ru/post/1663302/


All Articles