Remoting中数据序列化
点击次数:15 次 发布日期:2008-11-27 00:21:34 作者:源代码网
|
源代码网推荐 源代码网推荐一、 使用序列化类 源代码网推荐 源代码网推荐序列化一个类,并通过网络传输需要三步: 源代码网推荐 源代码网推荐1、将要序列化的类创建成一个library对象。 源代码网推荐 源代码网推荐2、编写一个发送程序来创建要序列化类的实例,并发送。 源代码网推荐 源代码网推荐3、编写一个接收程序从流中读取数据,并重新创建原来的序列化类。 源代码网推荐 源代码网推荐① 编写要序列化的类 源代码网推荐 源代码网推荐每个要通过网络传输数据的类必须在原代码文件里使用[Serializable]标签。这表明,类中所有的数据在传输时都将要被序列化。下面展示了如何创建一个可以序列化的类。 源代码网推荐 源代码网推荐using System; 源代码网推荐[Serializable] 源代码网推荐public class SerialEmployee 源代码网推荐{ 源代码网推荐public int EmployeeID 源代码网推荐public string LastName; 源代码网推荐public string FirstName; 源代码网推荐public int YearsService; 源代码网推荐public double Salary; 源代码网推荐public SerialEmployee() 源代码网推荐{ 源代码网推荐EmployeeID = 0; 源代码网推荐LastName = null; 源代码网推荐FirstName = null; 源代码网推荐YearsService = 0; 源代码网推荐Salary = 0.0; 源代码网推荐} 源代码网推荐} 源代码网推荐为了使用该类来传输数据,必须现创建一个library文件: 源代码网推荐 源代码网推荐csc /t:library SerialEmployee.cs 源代码网推荐 源代码网推荐② 编写一个传输程序 源代码网推荐 源代码网推荐创建数据类以后,可以创建一个程序来传输数据。可以使用BinaryFormatter和SoapFormatter类来序列化数据。 源代码网推荐 源代码网推荐BinaryFormatter将数据序列化为二进制流。通常在实际数据中,增加一些信息,例如类名和版本号信息。 源代码网推荐 源代码网推荐也可以使用SoapFormatter类使用XML格式来传输数据。使用XML的好处就是可以在任何系统和程序间传递数据。 源代码网推荐 源代码网推荐第一必须创建一个流的实例来传递数据。可以是任何类型的流,包括FileStream,MemoryStream,NetworkStream。然后,可以创建一个序列化类,使用Serialize()方法来通过流对象传递数据: 源代码网推荐 源代码网推荐Stream str = new FileStream( "testfile.bin", FileMode.Create, FileAccess.ReadWrite); 源代码网推荐IFormatter formatter = new BinaryFormatter(); 源代码网推荐formatter.Serialize(str, data); 源代码网推荐 源代码网推荐Iformatter类创建了一个用来序列化的类的实例(BinaryFormatter或者SoapFormatter),使用Serialize()类来将数据序列化 源代码网推荐 源代码网推荐using System; 源代码网推荐using System.IO; 源代码网推荐using System.Runtime.Serialization; 源代码网推荐using System.Runtime.Serialization.Formatters.Soap; 源代码网推荐class SoapTest 源代码网推荐{ 源代码网推荐public static void Main() 源代码网推荐{ 源代码网推荐SerialEmployee emp1 = new SerialEmployee(); 源代码网推荐SerialEmployee emp2 = new SerialEmployee(); 源代码网推荐emp1.EmployeeID = 1; 源代码网推荐emp1.LastName = "Blum"; 源代码网推荐emp1.FirstName = "Katie Jane"; 源代码网推荐emp1.YearsService = 12; 源代码网推荐emp1.Salary = 35000.50; 源代码网推荐emp2.EmployeeID = 2; 源代码网推荐emp2.LastName = "Blum"; 源代码网推荐emp2.FirstName = "Jessica"; 源代码网推荐emp2.YearsService = 9; 源代码网推荐emp2.Salary = 23700.30; 源代码网推荐Stream str = new FileStream("soaptest.xml", FileMode.Create, 源代码网推荐FileAccess.ReadWrite); 源代码网推荐IFormatter formatter = new SoapFormatter(); 源代码网推荐formatter.Serialize(str, emp1); 源代码网推荐formatter.Serialize(str, emp2); 源代码网推荐str.Close(); 源代码网推荐} 源代码网推荐} 源代码网推荐SoapFormatter类包含在System.Runtime.Serialization.Formatters.Soap命名空间,BinaryFormatter类包含在System.Runtime.Serialization.Formatters.Binary命名空间,Iformatter接口包含在System.Runtime.Serialization命名空间。 源代码网推荐 源代码网推荐编译代码:CSC /r:SerialEmployee.dll SoapTest.cs 源代码网推荐 源代码网推荐运行SoapTest.exe程序后,可以查看产生的soaptest.xml文件 源代码网推荐 源代码网推荐<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  源代码网推荐xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC=  源代码网推荐"http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV=  源代码网推荐"http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr=  源代码网推荐"http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle=  源代码网推荐"http://schemas.xmlsoap.org/soap/encoding/"> 源代码网推荐<SOAP-ENV:Body> 源代码网推荐<a1:SerialEmployee id="ref-1" xmlns:a1=  源代码网推荐"http://schemas.microsoft.com/clr/assem/SerialEmployee%2C%20Version%3D0. 源代码网推荐0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> 源代码网推荐<EmployeeID>1</EmployeeID> 源代码网推荐<LastName id="ref-3">Blum</LastName> 源代码网推荐<FirstName id="ref-4">Katie Jane</FirstName> 源代码网推荐<YearsService>12</YearsService> 源代码网推荐<Salary>35000.5</Salary> 源代码网推荐</a1:SerialEmployee> 源代码网推荐</SOAP-ENV:Body> 源代码网推荐</SOAP-ENV:Envelope> 源代码网推荐<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  源代码网推荐xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC=  源代码网推荐"http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV=  源代码网推荐"http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr=  源代码网推荐"http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle=  源代码网推荐"http://schemas.xmlsoap.org/soap/encoding/"> 源代码网推荐<SOAP-ENV:Body> 源代码网推荐<a1:SerialEmployee id="ref-1" xmlns:a1=  源代码网推荐"http://schemas.microsoft.com/clr/assem/SerialEmployee%2C%20Version%3D0. 源代码网推荐0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> 源代码网推荐<EmployeeID>2</EmployeeID> 源代码网推荐<LastName id="ref-3">Blum</LastName> 源代码网推荐<FirstName id="ref-4">Jessica</FirstName> 源代码网推荐<YearsService>9</YearsService> 源代码网推荐<Salary>23700.3</Salary> 源代码网推荐</a1:SerialEmployee> 源代码网推荐</SOAP-ENV:Body> 源代码网推荐</SOAP-ENV:Envelope> 源代码网推荐查看soaptest.xml文件,我们可以发现在序列化类中SOAP是如何定义每个数据元素。一个值得注意的重要XML数据特点如下: 源代码网推荐 源代码网推荐<a1:SerialEmployee id="ref-1" xmlns:a1=  源代码网推荐"http://schemas.microsoft.com/clr/assem/SerialEmployee%2C%20Version%3D0.Â0.0.0.%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> 源代码网推荐这里,XML中定义的数据使用了序列化数据类的实际类名。如果接收程序使用了另一个不同的类名,会和从流中读取的XML数据不匹配。类不匹配,读取将会失败。 源代码网推荐 源代码网推荐下面的代码展示了如何序列化数据,将数据传送到远程系统。 源代码网推荐 源代码网推荐using System; 源代码网推荐using System.Net; 源代码网推荐using System.Net.Sockets; 源代码网推荐using System.Runtime.Serialization; 源代码网推荐using System.Runtime.Serialization.Formatters.Binary; 源代码网推荐class BinaryDataSender 源代码网推荐{ 源代码网推荐public static void Main() 源代码网推荐{ 源代码网推荐SerialEmployee emp1 = new SerialEmployee(); 源代码网推荐SerialEmployee emp2 = new SerialEmployee(); 源代码网推荐emp1.EmployeeID = 1; 源代码网推荐emp1.LastName = "Blum"; 源代码网推荐emp1.FirstName = "Katie Jane"; 源代码网推荐emp1.YearsService = 12; 源代码网推荐emp1.Salary = 35000.50; 源代码网推荐emp2.EmployeeID = 2; 源代码网推荐emp2.LastName = "Blum"; 源代码网推荐emp2.FirstName = "Jessica"; 源代码网推荐emp2.YearsService = 9; 源代码网推荐emp2.Salary = 23700.30; 源代码网推荐TcpClient client = new TcpClient("127.0.0.1", 9050); 源代码网推荐IFormatter formatter = new BinaryFormatter(); 源代码网推荐NetworkStream strm = client.GetStream(); 源代码网推荐formatter.Serialize(strm, emp1); 源代码网推荐formatter.Serialize(strm, emp2); 源代码网推荐strm.Close(); 源代码网推荐client.Close(); 源代码网推荐} 源代码网推荐} 源代码网推荐因为BinaryFormatter和SoapFormatter类需要一个Stream对象来传递序列化的数据,所以要使用一个TCP Socket对象或者一个TcpClient对象来传递数据,不能直接使用UDP。 源代码网推荐 源代码网推荐③编写一个接收程序 源代码网推荐 源代码网推荐using System; 源代码网推荐using System.Net; 源代码网推荐using System.Net.Sockets; 源代码网推荐using System.Runtime.Serialization; 源代码网推荐using System.Runtime.Serialization.Formatters.Binary; 源代码网推荐class BinaryDataRcvr 源代码网推荐{ 源代码网推荐public static void Main() 源代码网推荐{ 源代码网推荐TcpListener server = new TcpListener(9050); 源代码网推荐server.Start(); 源代码网推荐TcpClient client = server.AcceptTcpClient(); 源代码网推荐NetworkStream strm = client.GetStream(); 源代码网推荐IFormatter formatter = new BinaryFormatter(); 源代码网推荐SerialEmployee emp1 = (SerialEmployee)formatter.Deserialize(strm); 源代码网推荐Console.WriteLine("emp1.EmployeeID = {0}", emp1.EmployeeID); 源代码网推荐Console.WriteLine("emp1.LastName = {0}", emp1.LastName); 源代码网推荐Console.WriteLine("emp1.FirstName = {0}", emp1.FirstName); 源代码网推荐Console.WriteLine("emp1.YearsService = {0}", emp1.YearsService); 源代码网推荐Console.WriteLine("emp1.Salary = {0} ", emp1.Salary); 源代码网推荐SerialEmployee emp2 = (SerialEmployee)formatter.Deserialize(strm); 源代码网推荐Console.WriteLine("emp2.EmployeeID = {0}", emp2.EmployeeID); 源代码网推荐Console.WriteLine("emp2.LastName = {0}", emp2.LastName); 源代码网推荐Console.WriteLine("emp2.FirstName = {0}", emp2.FirstName); 源代码网推荐Console.WriteLine("emp2.YearsService = {0}", emp2.YearsService); 源代码网推荐Console.WriteLine("emp2.Salary = {0}", emp2.Salary); 源代码网推荐strm.Close(); 源代码网推荐server.Stop(); 源代码网推荐} 源代码网推荐} 源代码网推荐 源代码网推荐二、 程序改进 源代码网推荐 源代码网推荐在前面的程序中有一个假设:发送者的所有数据都被接收者接收。如果数据丢失,调用Deserialize()方法会发生错误。一个简单的解决方法是将序列化数据放到MemoryStream对象中。MemoryStream对象将所有的序列化数据保存在内存中,可以很容易得到序列化数据的大小。当传递数据时,将数据大小和数据一起传递。 源代码网推荐 源代码网推荐using System; 源代码网推荐using System.IO; 源代码网推荐using System.Net; 源代码网推荐using System.Net.Sockets; 源代码网推荐using System.Runtime.Serialization; 源代码网推荐using System.Runtime.Serialization.Formatters.Soap; 源代码网推荐class BetterDataSender 源代码网推荐{ 源代码网推荐public void SendData (NetworkStream strm, SerialEmployee emp) 源代码网推荐{ 源代码网推荐IFormatter formatter = new SoapFormatter(); 源代码网推荐MemoryStream memstrm = new MemoryStream(); 源代码网推荐formatter.Serialize(memstrm, emp); 源代码网推荐byte[] data = memstrm.GetBuffer(); 源代码网推荐int memsize = (int)memstrm.Length; 源代码网推荐byte[] size = BitConverter.GetBytes(memsize); 源代码网推荐strm.Write(size, 0, 4); 源代码网推荐strm.Write(data, 0, memsize); 源代码网推荐strm.Flush(); 源代码网推荐memstrm.Close(); 源代码网推荐} 源代码网推荐public BetterDataSender() 源代码网推荐{ 源代码网推荐SerialEmployee emp1 = new SerialEmployee(); 源代码网推荐SerialEmployee emp2 = new SerialEmployee(); 源代码网推荐emp1.EmployeeID = 1; 源代码网推荐emp1.LastName = "Blum"; 源代码网推荐emp1.FirstName = "Katie Jane"; 源代码网推荐emp1.YearsService = 12; 源代码网推荐emp1.Salary = 35000.50; 源代码网推荐emp2.EmployeeID = 2; 源代码网推荐emp2.LastName = "Blum"; 源代码网推荐emp2.FirstName = "Jessica"; 源代码网推荐emp2.YearsService = 9; 源代码网推荐emp2.Salary = 23700.30; 源代码网推荐TcpClient client = new TcpClient("127.0.0.1", 9050); 源代码网推荐NetworkStream strm = client.GetStream(); 源代码网推荐SendData(strm, emp1); 源代码网推荐SendData(strm, emp2); 源代码网推荐strm.Close(); 源代码网推荐client.Close(); 源代码网推荐} 源代码网推荐public static void Main() 源代码网推荐{ 源代码网推荐BetterDataSender bds = new BetterDataSender(); 源代码网推荐} 源代码网推荐} 源代码网推荐接收数据程序如下: 源代码网推荐 源代码网推荐using System; 源代码网推荐using System.IO; 源代码网推荐using System.Net; 源代码网推荐using System.Net.Sockets; 源代码网推荐using System.Runtime.Serialization; 源代码网推荐using System.Runtime.Serialization.Formatters.Soap; 源代码网推荐class BetterDataRcvr 源代码网推荐{ 源代码网推荐private SerialEmployee RecvData (NetworkStream strm) 源代码网推荐{ 源代码网推荐MemoryStream memstrm = new MemoryStream(); 源代码网推荐byte[] data = new byte[4]; 源代码网推荐int recv = strm.Read(data, 0, 4); 源代码网推荐int size = BitConverter.ToInt32(data, 0); 源代码网推荐int offset = 0; 源代码网推荐while(size > 0) 源代码网推荐{ 源代码网推荐data = new byte[1024]; 源代码网推荐recv = strm.Read(data, 0, size); 源代码网推荐memstrm.Write(data, offset, recv); 源代码网推荐offset += recv; 源代码网推荐size -= recv; 源代码网推荐} 源代码网推荐IFormatter formatter = new SoapFormatter(); 源代码网推荐memstrm.Position = 0; 源代码网推荐SerialEmployee emp = (SerialEmployee)formatter.Deserialize(memstrm); 源代码网推荐memstrm.Close(); 源代码网推荐return emp; 源代码网推荐} 源代码网推荐public BetterDataRcvr() 源代码网推荐{ 源代码网推荐TcpListener server = new TcpListener(9050); 源代码网推荐server.Start(); 源代码网推荐TcpClient client = server.AcceptTcpClient(); 源代码网推荐NetworkStream strm = client.GetStream(); 源代码网推荐SerialEmployee emp1 = RecvData(strm); 源代码网推荐Console.WriteLine("emp1.EmployeeID = {0}", emp1.EmployeeID); 源代码网推荐Console.WriteLine("emp1.LastName = {0}", emp1.LastName); 源代码网推荐Console.WriteLine("emp1.FirstName = {0}", emp1.FirstName); 源代码网推荐Console.WriteLine("emp1.YearsService = {0}", emp1.YearsService); 源代码网推荐Console.WriteLine("emp1.Salary = {0} ", emp1.Salary); 源代码网推荐SerialEmployee emp2 = RecvData(strm); 源代码网推荐Console.WriteLine("emp2.EmployeeID = {0}", emp2.EmployeeID); 源代码网推荐Console.WriteLine("emp2.LastName = {0}", emp2.LastName); 源代码网推荐Console.WriteLine("emp2.FirstName = {0}", emp2.FirstName); 源代码网推荐Console.WriteLine("emp2.YearsService = {0}", emp2.YearsService); 源代码网推荐Console.WriteLine("emp2.Salary = {0}", emp2.Salary); 源代码网推荐strm.Close(); 源代码网推荐server.Stop(); 源代码网推荐} 源代码网推荐public static void Main() 源代码网推荐{ 源代码网推荐BetterDataRcvr bdr = new BetterDataRcvr(); 源代码网推荐} 源代码网推荐} 源代码网推荐 源代码网供稿. |
