加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何通过套接字发送外部库的可序列化对象?

发布时间:2020-12-15 21:04:11 所属栏目:百科 来源:网络整理
导读:我有一个简单的类库,只包含一种类型.现在我想通过使用套接字从客户端向服务器发送此类型的实例.客户端和服务器对SendingObject类型一无所知,这就是我需要加载程序集的原因. [Serializable] public class SendingObject : MarshalByRefObject { public string
我有一个简单的类库,只包含一种类型.现在我想通过使用套接字从客户端向服务器发送此类型的实例.客户端和服务器对SendingObject类型一无所知,这就是我需要加载程序集的原因.

[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}.");
        }
    }

这是我的客户的代码:

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,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,arrBytes.Length);
                memStream.Seek(0,SeekOrigin.Begin);
                Object obj = (Object)binForm.Deserialize(memStream);

                return obj;
            }
        }

此接收的对象将在服务器端反序列化.这是我服务器的代码.

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,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,arrBytes.Length);
            memStream.Seek(0,SeekOrigin.Begin);
            Object obj = (Object)binForm.Deserialize(memStream);

            return obj;
        }
    }

我的SendingObject可以序列化,但我尝试反序列化时出错.

The assembly can’t be found:”MyLibrary,Version=1.0.0.0,
Culture=neutral,PublicKeyToken=null”.

解决方法

好的,基本的东西,.NET中的二进制序列化可以用类型,汇编等信息来指出那些二进制文件.这就是为什么对于初学者来说,使用来序列化数据以保存对所有对象的引用会更容易.这里的例子:

// 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);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读