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可以序列化,但我尝试反序列化时出错.
解决方法
好的,基本的东西,.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); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |