Posted on 2008-05-06 17:39
Jerson Ju 阅读(123)
评论(1) 编辑 收藏 网摘 所属分类:
C#/DesignPattern
引用高人一段话:“
语言和编程本来是两回事情,却常常被初学者混淆不清。有些初学者,忙从于语言的选择,开发工具的跟进,疏忽了对编程思想和能力的养成;有些初学者,只专注于语言语法的学习,死扣一些没有必要的概念,真正写到程序却又一筹莫展;有些初学者,醉心于编程的技巧,陶醉于表面的实现,忽视了程序框架的设计与理解。
太多的新技术、太多的新术语、太多的开发环境、太多的编程平台、太多太多傻瓜化的工具,所有这些商业化的产物虽然方便了程序员,却使得他们疏于编程思想的养成,忽视对编码艺术的理解。 编程其实是需要大量实践和用心体会的工作。
希望此篇文章能给初学者以启发,真正的去理解编程,灵活的运用语言。”
好像有点跑题了。现在大多学c#,没有从C++ 或 delphi一路走来,大多是半路出身。所以当学习序列化这个技术点时候,只是学习语法。学完不知道为什么要这个技术,这个技术用来做什么的。
c#和java的前身是从c语言里发展而来的,只是封装了一下。取了个更好听的名字而已。下面假设我要在c语言里把一个数据发送的另一台电脑去。我们用socket就好了。但是我们大多用socket发送字符串。如果我想把多个数据发送到另一台电脑去呢。经典的案例是:如果我在网络游戏中,要把怪物的数据发送到客户端去(怪物包含:HP EXP x,y坐标 ID 等),那么我们用普通的发送字符串的方法去发的话。需要把要发的数据有规则的组成一个字符串,"|hp|Exp|x|y|ID|", 把这个字符串发送出去,在另一台电脑上去解析出需要的数据。这样做的缺点是加大网络流量、编译器无法检查错误、解析过于繁琐。我们有没有更好的办法呢?有就是把数据定义一个结构体,然后发送出去。
//socket 发送函数的原型
int send (
SOCKET s,
const char *buf,
int len,
int flags );
//-------------------------------------------------
struct monster
{
int hp;
int exp;
float x;
float y;
int id;
};
void main()
{
monster m1 = {90,88,34.3f,33.6.f,100002};
//这里我省略socket初始化以及获得socket对象的一些步骤了。只写主要发送过程
send(s,&m1,sizeof(m1),0);//这样就发送出去一个结构体对象了。
}
m1对象所有数据在内存中是连续存放的
所以我们告诉发送函数&m1就是内存起始地址,sizeof(m1)就是发送多长数据。
那么这样我们的数据就发送的远程客户端了。
接下来,我们在客户端拿我们想要的数据。
//socket接受数据函数原型
int recv(
SOCKET s,
char FAR *buf,
int len,
int flags
);
//----------------------
void main()
{
monster m1;
char buffer[255]={0};
//这里我省略socket初始化以及获得socket对象的一些步骤了。只写主要接受数据过程
recv(s,buffer,sizeof(monster),0);//这样就发送出去一个结构体对象了。
m1 = (monster)buffer;
//m1.hp m1.exp这样就可以访问发送过来的数据了。
}
这样就完成了c语言发送数据的整个过程了。不需要解析字符串,编译期可以检查错误。比如:hp是整形,如果你给它赋值double类型,编译都通不过。如果是以前拼凑字符串方式,你无论写什么编译器都认为你程序正确。
接下来,我们看C# java序列化,因为在c# java中我们发送数据,我们不能像c语言一样,通过指针访问要发送的内存中数据。(c# java都是调用操作系统的socket send recv发送数据的,只是封装了下。如果不相信,你可以用windbg去调试下。),我们无法或不建议我们程序员操作内存,所以java c#提供了一套序列化函数给我们,也就是序列化API。微软和sun公司帮我们做了访问内存的工作了。这就是序列化技术产生的原因。为什么要出现这个东西。我这里它产生的原因,怎么写c#的序列化,MSDN上已经很清楚了。