作者:李英林 日期:2010-04-14
代码下载:
服务器端代码: SERVER-Program.rar
客户端代码: Client.rar
一:服务器端代码,测试时首先要运行。可以在同台本地计算机上测试。
//提供使用XML方法,我们可以在采用不同语言编写的程序之间来回发送对象,
//而且从理论上讲还可以在不同平台之间发送对象。
/*
对 象
....|
....|
客 户<------- XML文档--------> 服务器
*/
/*
System.Xml.XmlSerialize命名空间提供了一个功能非常强大的工具集,可以把对象串行化到XML中。把对象串行化和反串行化到XML中替代了把对象保存为二进制格式,因此可以通过XML对对象进行其他处理。这将大大增强设计的灵活性。
串行化是把一个对象存入磁盘的过程。应用程序的另一部分,甚至另一个应用程序都可以反串行化对象,使它的状态与串行化之前相同。.NET Framework为此提供了两种方式。
本节将介绍System.Xml.Serialization命名空间。它包含的类可用于把对象串行化为XML文档或流。这表示对象的公共属性和公共字段将转换为XML元素和/或属性。
System.Xml.Serialization命名空间中最重要的类是XmlSerializer。要串行化对象,首先需要实例化一个XmlSerializer对象,指定要串行化的对象类型,然后实例化一个流/写入器对象,把文件写入流/文档。最后一步是在XmlSerializer上调用Serializer()方法,给它传送流/写入器对象和要串行化的对象。
被串行化的数据可以为基本类型的数据、字段、数组和XmlElements和XmlAttribute对象格式的内嵌XML。
为了从XML文档中反串行化对象,应执行上述过程的逆过程。即创建一个流/读取器对象和一个XmlSerializer对象,然后给DeSerializer()方法传送该流/读取器对象。这个方法返回反串行化的对象,但需要转换为正确的类型。
注意:
XML串行化器不能转换私有数据,只能转换公共数据,它也不能串行化对象图表。
但是,这并不是一个严格的限制。对类进行仔细设计,就很容易避免突破这个限制。如果需要串行化公共数据和私有数据,以及包含许多嵌套对象的对象图形,就可以使用System. Runtime. Serialization. Formatters.Binary命名空间。
使用System.Xml.Serialization类可以进行的其他工作如下所示:
● 确定数据应是一个属性还是元素
● 指定命名空间
● 改变属性或元素名
对象和XML文档之间的链接是给类加上注释的定制C#属性,这些属性可以告诉串行化程序如何写入数据。.
* XmlSerializer类的Serialize方法实际执行串行化,它有6个重载方法。第一个重载方法的参数是要写入数据的流,可以是Stream、TextWriter或XmlWriter。在本例中,
* 创建了一个基于CheckingAccount的对象myRestoredAccount。接着创建了基于XmlSerializer的对象myXmlfactory。XmlSerializer需要知道要串行化的对象的类型信息,
* 所以对要串行化的类型使用typeof关键字。在创建myXmlfactory对象后,调用Serialize方法,其参数是myRestoredAccount(基于Stream的对象)和要串行化的对象,确保完成后关闭该数据流。
该示例中服务器,对它进行反串行化.字段是private,只能通过CheckingAccount类中的get和set方法来访问
IP:
127.0.0.1是一个回送地址,这说明客户将要连接的服务器就是本机。
任意值11111是指定的虚拟端口,服务器必须监听这个端口
一旦客户与服务器建立了合法的通信,而且发送并获取了对象,客户就将终止。
首先要确认服务器端已经运行
本程序也讲到了手动抛出异常的方法
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Server
{
//定义对象CheckingAccount
[XmlRoot("account")]
public class CheckingAccount
{
private String strName;
//private int intAccountNyumber;
/// <summary>
/// Accessor method for strName
/// </summary>
[XmlElement("name")]
public String Name
{
get { return strName; }
set { strName = value; }
}
/// <summary>
/// Accessory Methods for intAccountNumber
/// </summary>
//[XmlElement("account_num")]
//public int AccountNumber
//{
// get { return intAccountNyumber; }
// set { AccountNumber = value; } //堆栈溢出错误???StackOverflowException 因执行堆栈溢出错误引发,不知原因
//}
//从 .NET Framework 2.0 版开始,将无法通过try-catch 块捕获StackOverflowException 对象,并且默认情况下将终止相应的进程。
/// <summary>
/// Defaultr constructor
/// </summary>
public CheckingAccount()
{
this.Name = "John Doe";
//this.AccountNumber = 54321;
Console.WriteLine("Creating Checking Account!");
}
}
class Server
{
//创建checkingAccount对象引用
//连接到scoket并监听;
//建立输入流;
//创建流
//从流读取字节;
//将对象串行化至流;
//关闭所有资源;
public Server()
{
TcpListener server = null;
TcpClient client = null;
try
{
//Creat our Socket Listener and strta it
server = new TcpListener(IPAddress.Parse("127.0.0.1"), 11111); );//两个参数表示IP地址和虚拟端口
//127.0.0.1是一个回送地址,这说明客户将要连接的服务器就是本机。
//任意值11111是指定的虚拟端口,服务器必须监听这个端口
//一旦客户与服务器建立了合法的通信,而且发送并获取了对象,客户就将终止。
//首先要确认服务器端已经运行
server.Start();
//Setup our input buffer
Byte[] bytes = new Byte[256];
//Loop indefuntely
while (true)
{
//Begain accepting incoming transmission in block mode
client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
//Open our stream
NetworkStream stream = client.GetStream();
//Read all the data from the stream
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
//Prepare a format that the serializer can read
MemoryStream ms = new MemoryStream(bytes);
//Pepare the serializer
XmlSerializer myXmlfactory = new XmlSerializer(typeof(CheckingAccount));
//Creat our CheckingAccount from the etream
CheckingAccount myRestoredAccount = (CheckingAccount)myXmlfactory.Deserialize(ms);
//Now demonstrate that the object is indeed created
Console.WriteLine("Name: {0},Account Number: {1}.", myRestoredAccount.Name, 0/*myRestoredAccount.AccountNumber*/);//AccountNumber StackOverflowException 因执行堆栈溢出错误引发,因此以0替代,不知原因
//Throw aN EXCEPTION TO EXIT THE LOOP
throw new Exception("ignore");
}
}
}
catch (Exception ex)
{
if (!ex.Message.Equals("ignore"))
{
Console.WriteLine("Exception: {0}", ex);
}
}
finally
{
//Close our resources
client.Close();
server.Stop();
}
}
}
class Program
{
static void Main(string[] args)
{
Server server=new Server ();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
二、客户端代码。
//提供使用XML方法,我们可以在采用不同语言编写的程序之间来回发送对象,
//而且从理论上讲还可以在不同平台之间发送对象。
/*
对 象
....|
....|
客 户<------- XML文档--------> 服务器
*/
/*
System.Xml.XmlSerialize命名空间提供了一个功能非常强大的工具集,可以把对象串行化到XML中。把对象串行化和反串行化到XML中替代了把对象保存为二进制格式,因此可以通过XML对对象进行其他处理。这将大大增强设计的灵活性。
串行化是把一个对象存入磁盘的过程。应用程序的另一部分,甚至另一个应用程序都可以反串行化对象,使它的状态与串行化之前相同。.NET Framework为此提供了两种方式。
本节将介绍System.Xml.Serialization命名空间。它包含的类可用于把对象串行化为XML文档或流。这表示对象的公共属性和公共字段将转换为XML元素和/或属性。
System.Xml.Serialization命名空间中最重要的类是XmlSerializer。要串行化对象,首先需要实例化一个XmlSerializer对象,指定要串行化的对象类型,然后实例化一个流/写入器对象,把文件写入流/文档。最后一步是在XmlSerializer上调用Serializer()方法,给它传送流/写入器对象和要串行化的对象。
被串行化的数据可以为基本类型的数据、字段、数组和XmlElements和XmlAttribute对象格式的内嵌XML。
为了从XML文档中反串行化对象,应执行上述过程的逆过程。即创建一个流/读取器对象和一个XmlSerializer对象,然后给DeSerializer()方法传送该流/读取器对象。这个方法返回反串行化的对象,但需要转换为正确的类型。
注意:
XML串行化器不能转换私有数据,只能转换公共数据,它也不能串行化对象图表。
但是,这并不是一个严格的限制。对类进行仔细设计,就很容易避免突破这个限制。如果需要串行化公共数据和私有数据,以及包含许多嵌套对象的对象图形,就可以使用System. Runtime. Serialization. Formatters.Binary命名空间。
使用System.Xml.Serialization类可以进行的其他工作如下所示:
● 确定数据应是一个属性还是元素
● 指定命名空间
● 改变属性或元素名
对象和XML文档之间的链接是给类加上注释的定制C#属性,这些属性可以告诉串行化程序如何写入数据。.
* XmlSerializer类的Serialize方法实际执行串行化,它有6个重载方法。第一个重载方法的参数是要写入数据的流,可以是Stream、TextWriter或XmlWriter。在本例中,
* 创建了一个基于CheckingAccount的对象myRestoredAccount。接着创建了基于XmlSerializer的对象myXmlfactory。XmlSerializer需要知道要串行化的对象的类型信息,
* 所以对要串行化的类型使用typeof关键字。在创建myXmlfactory对象后,调用Serialize方法,其参数是myRestoredAccount(基于Stream的对象)和要串行化的对象,确保完成后关闭该数据流。
该示例中服务器,对它进行反串行化.字段是private,只能通过CheckingAccount类中的get和set方法来访问
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Net;
using System.Net.Sockets;
//using System.Text;
namespace Client
{
//定义对象CheckingAccount
[XmlRoot("account")]
public class CheckingAccount
{
private String strName;
private int intAccountNyumber;
/// <summary>
/// Accessor method for strName
/// </summary>
[XmlElement ("name")]
public String Name
{
get { return strName ;}
set{strName =value ;}
}
/// <summary>
/// Accessory Methods for intAccountNumber
/// </summary>
[XmlElement("account_num")]
public int AccountNumber
{
get{return intAccountNyumber ;}
set{intAccountNyumber =value ;}
}
/// <summary>
/// Defaultr constructor
/// </summary>
public CheckingAccount()
{
this .Name ="Kinglion";
this.AccountNumber=54321;
Console .WriteLine ("Creating Checking Account!");
}
}
class Client
{
//创建checkingAccount对象
//创建scoket;
//将对象串行化为XML;
//创建流;
//将对象串行化至流;
//关闭资源;
//关闭流
public void Connect() //static
{
try
{
CheckingAccount myAccount=new CheckingAccount ();
//Creat our TCP Socket
TcpClient client=new TcpClient ("127.0.0.1",11111);//两个参数表示IP地址和虚拟端口
//127.0.0.1是一个回送地址,这说明客户将要连接的服务器就是本机。
//任意值11111是指定的虚拟端口,服务器必须监听这个端口
//一旦客户与服务器建立了合法的通信,而且发送并获取了对象,客户就将终止。
//首先要确认服务器端已经运行
//Prepare to serialize our CheckingAccount object to XML
XmlSerializer myXmlFactory=new XmlSerializer (typeof (CheckingAccount ));
//Create our TCP Stream
NetworkStream stream=client .GetStream();
//Serialize our object to the TCP Stream
myXmlFactory .Serialize (stream ,myAccount );
//Close all of our resources
stream .Close();
client .Close();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
catch (Exception ex)
{
Console .WriteLine("Exception: {0}",ex);
}
}
static void Main(string[] args)
{
Client client=new Client ();
client.Connect();
//Console.WriteLine("Press any key to continue...");
//Console.ReadKey();
}
}
}
运行结果:
首先启动服务器端程序:SERVER,
然后运行客户端程序:CLIENT,
服务器端显示:
Connected!
Creating Checking Account!
Name: Kinglion,Account Number: 0.
Press any key to continue...
运行客户端程序:CLIENT
客户端显示:
Creating Checking Account!
Press any key to continue...
联系客服