﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-【Xine】中文站-文章分类-View Collection</title><link>http://www.blogjava.net/xine/category/11748.html</link><description>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I love you not because of who you are,but because of who I am when I am with you.&lt;br&gt;&lt;br&gt;</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 02:55:35 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 02:55:35 GMT</pubDate><ttl>60</ttl><item><title>OICQ服务器系统通讯协议</title><link>http://www.blogjava.net/xine/articles/49775.html</link><dc:creator>【Xine】中文站</dc:creator><author>【Xine】中文站</author><pubDate>Thu, 01 Jun 2006 12:00:00 GMT</pubDate><guid>http://www.blogjava.net/xine/articles/49775.html</guid><wfw:comment>http://www.blogjava.net/xine/comments/49775.html</wfw:comment><comments>http://www.blogjava.net/xine/articles/49775.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xine/comments/commentRss/49775.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xine/services/trackbacks/49775.html</trackback:ping><description><![CDATA[协议说明： <br />协议由报文头(T)+发送者(T)+接收者(T)+报文类型（T）+报文长度(L)+报文内容组成 <br />发送者和接收者是系统内的程序种类,OICQ服务器0x01,传真服务器0x02,WEB服务器0x03,打印服务器是0x04,聊天服务器是0x05,OICQ用户是0x0A。 
<p>OICQ用户到OICQ服务器的通讯协议 引导符 （0x81+0x0A+0x01） <br />报文类型 报文内容 报文说明 <br />0x01 昵称（S）+肖像（M）+用户密码（S）+性别（T）+年龄（T）+真实姓名（S）+国家/地区（T）+省（T）+市（S）+地址（S）+邮编（S）+学历（T）+毕业院校（S）+职业（T）+电话（S）+寻呼（S）+电邮（S）+爱好（S）+说明（S）+身份验证（T）新用户注册，身份验证用于当有人要将他加入好友时询问是否允许 <br />0x02 服务号（L）+密码（S）+注册方式（T）老用户注册，方式分为0正常，1隐身 <br />0x03 服务号（L）+对方服务号（L）+内容（S） 发送信息到某人 <br />0x04 服务号（L）+组号（L）+内容（S） 广播信息，组号=0为全体 <br />0x05 服务号（L）+朋友服务号（L） 查看朋友资料 <br />0x06 服务号（L）+组名称（S） 增加组 <br />0x07 服务号（L）+组编号（T）+组名称（S） 修改组名称 <br />0x08 服务号（L）+组编号（T） 删除组 <br />0x09 服务号（L）+移动人数（T）+{朋友服务号（L）+目的组号（T）} 移动组成员 <br />0x0a 服务号（L）+起始编号(L)+回传个数（T）+查找标志(T) 看谁在线上 <br />查找标志 1=向小找 2=向大找 <br />0x0b 服务号（L）+SQL语句（S） 自定义查找 <br />0x0c 服务号（L）+朋友服务号（L） 增加好友 <br />0x0d 服务号（L）+朋友服务号（L）+加入原因（S） 请求加入好友 <br />0x0e 服务号（L）+朋友服务号（L） 删除好友 <br />0x10 服务号（L）+显示模式（T） 更改显示方式 1上线2隐藏3免打扰4离线 <br />0x11 服务号（L）+监视服务号（L） 监视某人谈话 <br />0x12 服务号（L）+昵称（S）+肖像（M）+用户密码（S）+性别（T）+年龄（T）+真实姓名（S）+国家/地区（T）+省（T）+市（S）+地址（S）+邮编（S）+学历（T）+毕业院校（S）+职业（T）+电话（S）+寻呼（S）+电邮（S）+爱好（S）+说明（S）+身份验证（T）更改用户基本信息 <br />0x13 服务号(L)+朋友服务号（L）+文件名(S)+文件长度(L) 请求发送文件 <br />0x14 服务号（L）+朋友服务号（L）+允许/拒绝 是否允许发送文件 <br />0x15 服务号（L）+朋友服务号（L）+文件内容（B） 发送文件 <br />0x16 服务号（L） 连接测试报文 <br />0x17 服务号（L）+朋友服务号（L）+同意标志(T) 应答对方请求加入好友 <br />0=拒绝 <br />1=同意 </p><p>OICQ服务器到OICQ的通讯协议 <br />报文类型 报文内容 报文说明 <br />0x01 成功/失败（T）+服务号（L） 新用户注册结果返回 <br />0x02 成功/失败（T）+组个数（T）+{组名称（S）+组编号（T）+朋友个数（T）+{朋友服务号（L）+肖像编号（T）+朋友状态(T)+朋友昵称（S）} 老用户注册结果返回 <br />朋友状态 <br />1=上线=2隐藏=3免打扰4离线 <br />0x03 标志(T) + 朋友服务号（L）+信息（S）+信息类型（T） 标志 1=系统 2=用户 <br />发送消息，服务号=0是系统消息 <br />1=用户某某已经把你加为好友 <br />2=用户某某请求你通过身份验证 <br />3=用户某某同意了你的验证要求 <br />4=用户某某拒绝了你的验证请求 <br />0x04 成功/失败（T）+朋友服务号(L)+昵称（S）+肖像（M）+性别（T）+年龄（T）+真实姓名（S）+国家/地区（T）+省（T）+市（S）+地址（S）+邮编（S）+学历（T）+毕业院校（S）+职业（T）+电话（S）+寻呼（S）+电邮（S）+爱好（S）+说明（S）朋友信息回送 <br />0x05 成功/失败（T）+组编号（T）+组名称（S） 增加组结果回送 1/0 <br />0x06 成功/失败（T）+组编号（T）+组名称（S）修改组名称结果回送1/0 <br />0x07 成功/失败（T）+组编号（T） 删除组结果回送1/0 <br />0x08 成功/失败（T） 移动组成员结果回送1/0 <br />0x09 成功/失败（T）+在线个数（T）+{服务号（L）+昵称（S）+肖像（M）+省（T）+市（S）} 查找在线人员结果回送 <br />0x0a 成功/失败（T）+找到个数（T）+{服务号（L）+昵称（S）+肖像（M）+省（T）+市（S）} 自定义查找结果回送（最多50） <br />0x0b 标志（T）+朋友服务号（L） 增加好友结果回送标志 <br />0=数据库失败 <br />=1成功 <br />=2需要身份验证 <br />=3对方不允许加入 <br />=4需要身份验证且不在线 <br />0x0c 朋友服务号(L)+昵称（S）+肖像号（M）+朋友状态(T) 给在线用户增加好友 <br />0x0e 成功/失败（T）+朋友服务号（L） 删除好友结果回送 <br />0x10 服务号（L）+显示模式（T） 显示模式回送 =1上线=2隐藏=3免打扰4离线 <br />0x11 成功/失败 更改用户基本信息结果回送 <br />0x12 朋友服务号（L）+文件名（S）+文件长度（L） 请求发送文件 <br />0x13 朋友服务号（L）+允许/拒绝 是否允许发送文件 1允许 0拒绝 <br />0x14 朋友服务号（L）+文件内容（B） 发送文件 <br />0x15 朋友服务号（L）+当前状态（T）朋友状态回送（系统发送）=1上线=2隐藏=3免打扰4离线 <br />0x16 服务号（L） 连接测试 </p><img src ="http://www.blogjava.net/xine/aggbug/49775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xine/" target="_blank">【Xine】中文站</a> 2006-06-01 20:00 <a href="http://www.blogjava.net/xine/articles/49775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类似于QQ游戏百万人同时在线的服务器架构实现（转）</title><link>http://www.blogjava.net/xine/articles/49736.html</link><dc:creator>【Xine】中文站</dc:creator><author>【Xine】中文站</author><pubDate>Thu, 01 Jun 2006 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/xine/articles/49736.html</guid><wfw:comment>http://www.blogjava.net/xine/comments/49736.html</wfw:comment><comments>http://www.blogjava.net/xine/articles/49736.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xine/comments/commentRss/49736.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xine/services/trackbacks/49736.html</trackback:ping><description><![CDATA[
		<span class="unnamed3">QQ游戏于前几日终于突破了百万人同时在线的关口，向着更为远大的目标迈进，这让其它众多传统的棋牌休闲游戏平台黯然失色，相比之下，联众似乎已经根本不是QQ的对手，因为QQ除了这100万的游戏在线人数外，它还拥有3亿多的注册量（当然很多是重复注册的）以及QQ聊天软件900万的同时在线率，我们已经可以预见未来由QQ构建起来的强大棋牌休闲游戏帝国。<br />　　那么，在技术上，QQ游戏到底是如何实现百万人同时在线并保持游戏高效率的呢？<br />　　事实上，针对于任何单一的网络服务器程序，其可承受的同时连接数目是有理论峰值的，通过C＋＋中对TSocket的定义类型：word，我们可以判定这个连接理论峰值是65535，也就是说，你的单个服务器程序，最多可以承受6万多的用户同时连接。但是，在实际应用中，能达到一万人的同时连接并能保证正常的数据交换已经是很不容易了，通常这个值都在2000到5000之间，据说QQ的单台服务器同时连接数目也就是在这个值这间。<br />　　如果要实现2000到5000用户的单服务器同时在线，是不难的。在windows下，比较成熟的技术是采用IOCP－－完成端口。与完成端口相关的资料在网上和CSDN论坛里有很多，感兴趣的朋友可以自己搜索一下。只要运用得当，一个完成端口服务器是完全可以达到2K到5K的同时在线量的。但，5K这样的数值离百万这样的数值实在相差太大了，所以，百万人的同时在线是单台服务器肯定无法实现的。<br />　　要实现百万人同时在线，首先要实现一个比较完善的完成端口服务器模型，这个模型要求至少可以承载2K到5K的同时在线率（当然，如果你MONEY多，你也可以只开发出最多允许100人在线的服务器）。在构建好了基本的完成端口服务器之后，就是有关服务器组的架构设计了。之所以说这是一个服务器组，是因为它绝不仅仅只是一台服务器，也绝不仅仅是只有一种类型的服务器。<br />　　简单地说，实现百万人同时在线的服务器模型应该是：登陆服务器＋大厅服务器＋房间服务器。当然，也可以是其它的模型，但其基本的思想是一样的。下面，我将逐一介绍这三类服务器的各自作用。<br />　　登陆服务器：一般情况下，我们会向玩家开放若干个公开的登陆服务器，就如QQ登陆时让你选择的从哪个QQ游戏服务器登陆一样，QQ登陆时让玩家选择的六个服务器入口实际上就是登陆服务器。登陆服务器主要完成负载平衡的作用。详细点说就是，在登陆服务器的背后，有N个大厅服务器，登陆服务器只是用于为当前的客户端连接选择其下一步应该连接到哪个大厅服务器，当登陆服务器为当前的客户端连接选择了一个合适的大厅服务器后，客户端开始根据登陆服务器提供的信息连接到相应的大厅上去，同时客户端断开与登陆服务器的连接，为其他玩家客户端连接登陆服务器腾出套接字资源。在设计登陆服务器时，至少应该有以下功能：N个大厅服务器的每一个大厅服务器都要与所有的登陆服务器保持连接，并实时地把本大厅服务器当前的同时在线人数通知给各个登陆服务器，这其中包括：用户进入时的同时在线人数增加信息以及用户退出时的同时在线人数减少信息。这里的各个大厅服务器同时在线人数信息就是登陆服务器为客户端选择某个大厅让其登陆的依据。举例来说，玩家A通过登陆服务器1连接到登陆服务器，登陆服务器开始为当前玩家在众多的大厅服务器中根据哪一个大厅服务器人数比较少来选择一个大厅，同时把这个大厅的连接IP和端口发给客户端，客户端收到这个IP和端口信息后，根据这个信息连接到此大厅，同时，客户端断开与登陆服务器之间的连接，这便是用户登陆过程中，在登陆服务器这一块的处理流程。<br />　　大厅服务器：大厅服务器，是普通玩家看不到的服务器，它的连接IP和端口信息是登陆服务器通知给客户端的。也就是说，在QQ游戏的本地文件中，具体的大厅服务器连接IP和端口信息是没有保存的。大厅服务器的主要作用是向玩家发送游戏房间列表信息，这些信息包括：每个游戏房间的类型，名称，在线人数，连接地址以及其它如游戏帮助文件URL的信息。从界面上看的话，大厅服务器就是我们输入用户名和密码并校验通过后进入的游戏房间列表界面。大厅服务器，主要有以下功能：一是向当前玩家广播各个游戏房间在线人数信息；二是提供游戏的版本以及下载地址信息；三是提供各个游戏房间服务器的连接IP和端口信息；四是提供游戏帮助的URL信息；五是提供其它游戏辅助功能。但在这众多的功能中，有一点是最为核心的，即：为玩家提供进入具体的游戏房间的通道，让玩家顺利进入其欲进入的游戏房间。玩家根据各个游戏房间在线人数，判定自己进入哪一个房间，然后双击服务器列表中的某个游戏房间后玩家开始进入游戏房间服务器。<br />　　游戏房间服务器：游戏房间服务器，具体地说就是如“斗地主1”，“斗地主2”这样的游戏房间。游戏房间服务器才是具体的负责执行游戏相关逻辑的服务器。这样的游戏逻辑分为两大类：一类是通用的游戏房间逻辑，如：进入房间，离开房间，进入桌子，离开桌子以及在房间内说话等；第二类是游戏桌子逻辑，这个就是各种不同类型游戏的主要区别之处了，比如斗地主中的叫地主或不叫地主的逻辑等，当然，游戏桌子逻辑里也包括有通用的各个游戏里都存在的游戏逻辑，比如在桌子内说话等。总之，游戏房间服务器才是真正负责执行游戏具体逻辑的服务器。<br />　　这里提到的三类服务器，我均采用的是完成端口模型，每个服务器最多连接数目是5000人，但是，我在游戏房间服务器上作了逻辑层的限定，最多只允许300人同时在线。其他两个服务器仍然允许最多5000人的同时在线。如果按照这样的结构来设计，那么要实现百万人的同时在线就应该是这样：首先是大厅，1000000/5000＝200。也就是说，至少要200台大厅服务器，但通常情况下，考虑到实际使用时服务器的处理能力和负载情况，应该至少准备250台左右的大厅服务器程序。另外，具体的各种类型的游戏房间服务器需要多少，就要根据当前玩各种类型游戏的玩家数目分别计算了，比如斗地主最多是十万人同时在线，每台服务器最多允许300人同时在线，那么需要的斗地主服务器数目就应该不少于：100000/300=333，准备得充分一点，就要准备350台斗地主服务器。<br />　　除正常的玩家连接外，还要考虑到：<br />　　对于登陆服务器，会有250台大厅服务器连接到每个登陆服务器上，这是始终都要保持的连接；<br />　　而对于大厅服务器而言，如果仅仅有斗地主这一类的服务器，就要有350多个连接与各个大厅服务器始终保持着。所以从这一点看，我的结构在某些方面还存在着需要改进的地方，但核心思想是：尽快地提供用户登陆的速度，尽可能方便地让玩家进入游戏中。</span>
<img src ="http://www.blogjava.net/xine/aggbug/49736.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xine/" target="_blank">【Xine】中文站</a> 2006-06-01 17:35 <a href="http://www.blogjava.net/xine/articles/49736.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Web开发技术发展史话</title><link>http://www.blogjava.net/xine/articles/49724.html</link><dc:creator>【Xine】中文站</dc:creator><author>【Xine】中文站</author><pubDate>Thu, 01 Jun 2006 09:20:00 GMT</pubDate><guid>http://www.blogjava.net/xine/articles/49724.html</guid><wfw:comment>http://www.blogjava.net/xine/comments/49724.html</wfw:comment><comments>http://www.blogjava.net/xine/articles/49724.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xine/comments/commentRss/49724.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xine/services/trackbacks/49724.html</trackback:ping><description><![CDATA[
		<span class="unnamed3">
				<span class="f14">　　讨论Web开发技术的历史，当然要先说说Web的起源。众所周知，Web这个Internet上最热门的应用架构是由Tim Berners-Lee发明的。Web的前身是1980年Tim Berners-Lee负责的Enquire（Enquire Within Upon Everything的简称）项目。1990年11月，第一个Web服务器nxoc01.cern.ch开始运行，Tim Berners-Lee在自己编写的图形化Web浏览器"WorldWideWeb"上看到了最早的Web页面。1991年，CERN（European Particle Physics Laboratory）正式发布了Web技术标准。目前，与Web相关的各种技术标准都由著名的W3C组织（World Wide Web Consortium）管理和维护。<br /><br />　　 从技术层面看，Web架构的精华有三处：用超文本技术（HTML）实现信息与信息的连接；用统一资源定位技术（URI）实现全球信息的精确定位；用新的应用层协议（HTTP）实现分布式的信息共享。这三个特点无一不与信息的分发、获取和利用有关。其实，Tim Berners-Lee早就明确无误地告诉我们："Web是一个抽象的（假想的）信息空间。"也就是说，作为Internet上的一种应用架构，Web的首要任务就是向人们提供信息和信息服务。<br /><br />　　 很可惜，在Web应用日新月异的今天，许多搞技术的人似乎已经忘记了Web架构的设计初衷。他们在自己开发的网站或Web应用中大肆堆砌各种所谓的"先进"技术，但最终用户能够在这些网站或应用中获得的有价值信息却寥寥无几。这个问题绝不像评论者常说的"有路无车"或"信息匮乏"那么简单。一个Web开发者倘若忘记了Web技术的最终目标是提供信息和信息服务，他的愚蠢程度就丝毫不亚于一个在足球场上只知道卖弄技巧，却忘记了射门得分的大牌球星。从这个角度来说，评价一种Web开发技术优劣的标准只有一个，那就是看这种技术能否在最恰当的时间和最恰当的地点，以最恰当的方式，为最需要信息的人提供最恰当的信息服务。<br /><br />　　<strong>客户端技术的萌芽和演进</strong><br /><br />　　 Web是一种典型的分布式应用架构。Web应用中的每一次信息交换都要涉及到客户端和服务端两个层面。因此，Web开发技术大体上也可以被分为客户端技术和服务端技术两大类。我们先来谈谈客户端技术的萌芽和演进过程。<br /><br />　　 Web客户端的主要任务是展现信息内容，而HTML语言则是信息展现的最有效载体之一。作为一种实用的超文本语言，HTML的历史最早可以追溯到上世纪四十年代。1945年，Vannevar Bush在一篇文章中阐述了文本和文本之间通过超级链接相互关联的思想，并在文中给出了一种能实现信息关联的计算机Memex的设计方案。Doug Engelbart等人则在1960年前后，对信息关联技术做了最早的实验。与此同时，Ted Nelson正式将这种信息关联技术命名为超文本（Hypertext）技术。1969年，IBM的Charles Goldfarb发明了可用于描述超文本信息的GML（Generalized Markup Language）语言。1978到1986年间，在ANSI等组织的努力下，GML语言进一步发展成为著名的SGML语言标准。当Tim Berners-Lee和他的同事们在1989年试图创建一个基于超文本的分布式应用系统时，Tim Berners-Lee意识到，SGML是描述超文本信息的一个上佳方案，但美中不足的是，SGML过于复杂，不利于信息的传递和解析。于是，Tim Berners-Lee对SGML语言做了大刀阔斧的简化和完善。1990年，第一个图形化的Web浏览器"WorldWideWeb"终于可以使用一种为Web度身定制的语言--HTML来展现超文本信息了。<br /><br />　　 最初的HTML语言只能在浏览器中展现静态的文本或图像信息，这满足不了人们对信息丰富性和多样性的强烈需求--这件事情最终的结果是，由静态技术向动态技术的转变成为了Web客户端技术演进的永恒定律。<br /><br />　 　能存储、展现二维动画的GIF图像格式早在1989年就已发展成熟。Web出现后，GIF第一次为HTML页面引入了动感元素。但更大的变革来源于1995年Java语言的问世。Java语言天生就具备的平台无关的特点，让人们一下子找到了在浏览器中开发动态应用的捷径。1996年，著名的Netscape浏览器在其2.0版中增加了对JavaApplets和JavaScript的支持。Netscape的冤家对头，Microsoft的IE 3.0也在这一年开始支持Java技术。现在，喜欢动画、喜欢交互操作、喜欢客户端应用的开发人员可以用Java或JavaScript语言随心所欲地丰富HTML页面的功能了。顺便说一句，JavaScript语言在所有客户端开发技术中占有非常独特的地位：它是一种以脚本方式运行的，简化了的Java语言，这也是脚本技术第一次在Web世界里崭露头角。为了用纯Microsoft的技术与JavaScript抗衡，Microsoft还为1996年的IE 3.0设计了另一种后来也声名显赫的脚本语言--VBScript语言。<br /><br />　 　真正让HTML页面又酷又炫、动感无限的是CSS（Cascading Style Sheets）和DHTML（Dynamic HTML）技术。1996年底，W3C提出了CSS的建议标准，同年，IE 3.0引入了对CSS的支持。CSS大大提高了开发者对信息展现格式的控制能力。1997年的Netscape 4.0不但支持CSS，而且增加了许多Netscape公司自定义的动态HTML标记，这些标记在CSS的基础上，让HTML页面中的各种要素"活动"了起来。1997年，Microsoft发布了IE 4.0，并将动态HTML标记、CSS和动态对象模型（DHTML Object Model）发展成了一套完整、实用、高效的客户端开发技术体系，Microsoft称其为DHTML。同样是实现HTML页面的动态效果，DHTML技术无需启动Java虚拟机或其他脚本环境，可以在浏览器的支持下，获得更好的展现效果和更高的执行效率。今天，已经很少有哪个HTML页面的开发者还会对CSS和DHTML技术视而不见了。<br /><br />　 　为了在HTML页面中实现音频、视频等更为复杂的多媒体应用，1996年的Netscape 2.0成功地引入了对QuickTime插件的支持，插件这种开发方式也迅速风靡了浏览器的世界。在Windows平台上，Microsoft将客户端应用集成的赌注押到了1990年代中期刚刚问世的COM和ActiveX身上。1996年，IE 3.0正式支持在HTML页面中插入ActiveX控件的功能，这为其他厂商扩展Web客户端的信息展现方式开辟了一条自由之路。1999年，Realplayer插件先后在Netscape和IE浏览器中取得了成功，与此同时，Microsoft自己的媒体播放插件Media Player也被预装到了各种Windows版本之中。同样值得纪念的还有Flash插件的横空出世：1990年代初期，Jonathan Gay在FutureWave公司开发了一种名为Future Splash Animator的二维矢量动画展示工具，1996年，Macromedia公司收购了FutureWave，并将Jonathan Gay的发明改名为我们熟悉的Flash。从此，Flash动画成了Web开发者表现自我、展示个性的最佳方式。<br /><br />　 　除了编写HTML页面之外，客户端应用的开发者还可以利用一些成熟的技术将浏览器的功能添加到自己的应用程序中。从1992年开始，W3C就免费向开发者提供libwww开发库。借助libwww，我们可以自己编写Web浏览器和Web搜索工具，也可以分析、编辑或显示HTML页面。1999年，Microsoft在IE 5.0中引入的HTAs（HTML Applications）技术则允许我们直接将HTML页面转换为一个真正的应用程序。从1997年的IE 4.0开始，Microsoft为开发者提供了WebBrowser控件和其他相关的COM接口，允许程序员在自己的程序中直接嵌入浏览器窗口，或调用各种浏览器的功能，如分析或编辑HTML页面等。Windows 98及其后的Windows操作系统甚至还利用WSH（Windows Script Host）技术将原本只在浏览器中运行的JavaScript、VBScript变成了可以在WIN32环境下使用的通用脚本语言，这大概也可算作我们对Web客户端开发技术的一种巧妙利用吧。<br /><br />　　<strong>服务端技术的成熟与发展</strong><br /><br />　 　与客户端技术从静态向动态的演进过程类似，Web服务端的开发技术也是由静态向动态逐渐发展、完善起来的。<br /><br />　 　最早的Web服务器简单地响应浏览器发来的HTTP请求，并将存储在服务器上的HTML文件返回给浏览器。一种名为SSI（Server Side Includes）的技术可以让Web服务器在返回HTML文件前，更新HTML文件的某些内容，但其功能非常有限。第一种真正使服务器能根据运行时的具体情况，动态生成HTML页面的技术是大名鼎鼎的CGI（Common Gateway Interface）技术。1993年，CGI 1.0的标准草案由NCSA（National Center for Supercomputing Applications）提出，1995年，NCSA开始制定CGI 1.1标准，1997年，CGI 1.2也被纳入了议事日程。CGI技术允许服务端的应用程序根据客户端的请求，动态生成HTML页面，这使客户端和服务端的动态信息交换成为了可能。随着CGI技术的普及，聊天室、论坛、电子商务、信息查询、全文检索等各式各样的Web应用蓬勃兴起，人们终于可以享受到信息检索、信息交换、信息处理等更为便捷的信息服务了。<br /><br />　 　早期的CGI程序大多是编译后的可执行程序，其编程语言可以是C、C++、Pascal等任何通用的程序设计语言。为了简化CGI程序的修改、编译和发布过程，人们开始探寻用脚本语言实现CGI应用的可行方式。在此方面，不能不提的是Larry Wall于1987年发明的Perl语言。Perl结合了C语言的高效以及sh、awk等脚本语言的便捷，似乎天生就适用于CGI程序的编写。1995年，第一个用Perl写成的CGI程序问世。很快，Perl在CGI编程领域的风头就盖过了它的前辈C语言。随后，Python等著名的脚本语言也陆续加入了CGI编程语言的行列。<br /><br />　 　1994年，Rasmus Lerdorf发明了专用于Web服务端编程的PHP（Personal Home Page Tools）语言。与以往的CGI程序不同，PHP语言将HTML代码和PHP指令合成为完整的服务端动态页面，Web应用的开发者可以用一种更加简便、快捷的方式实现动态Web功能。1996年，Microsoft借鉴PHP的思想，在其Web服务器IIS 3.0中引入了ASP技术。ASP使用的脚本语言是我们熟悉的VBScript和JavaScript。借助Microsoft Visual Studio等开发工具在市场上的成功，ASP迅速成为了Windows系统下Web服务端的主流开发技术。当然，以Sun公司为首的Java阵营也不会示弱。1997年，Servlet技术问世，1998年，JSP技术诞生。Servlet和JSP的组合（还可以加上JavaBean技术）让Java开发者同时拥有了类似CGI程序的集中处理功能和类似PHP的HTML嵌入功能，此外，Java的运行时编译技术也大大提高了Servlet和JSP的执行效率--这也正是Servlet和JSP被后来的J2EE平台吸纳为核心技术的原因之一。<br /><br />　　<strong>两种重要的企业开发平台</strong><br /><br />　 　Web服务端开发技术的完善使开发复杂的Web应用成为了可能。在此起彼伏的电子商务大潮中，为了适应企业级应用开发的各种复杂需求，为了给最终用户提供更可靠、更完善的信息服务，两个最重要的企业级开发平台--J2EE和.NET在2000年前后分别诞生于Java和Windows阵营，它们随即就在企业级Web开发领域展开了你死我活的拼争。平台之争让整个Web世界在最近的几年里不得安宁，但从某种意义上说，也正是这种针锋相对的竞争关系促使了Web开发技术以前所未有的速度提高和跃进。<br /><br />　 　J2EE是纯粹基于Java的解决方案。1998年，Sun发布了EJB 1.0标准。EJB为企业级应用中必不可少的数据封装、事务处理、交易控制等功能提供了良好的技术基础。至此，J2EE平台的三大核心技术Servlet、JSP和EJB都已先后问世。1999年，Sun正式发布了J2EE的第一个版本。紧接着，遵循J2EE标准，为企业级应用提供支撑平台的各类应用服务软件争先恐后地涌现了出来。IBM的WebSphere、BEA的WebLogic都是这一领域里最为成功的商业软件平台。随着开源运动的兴起，JBoss等开源世界里的应用服务新秀也吸引了许多用户的注意力。到2003年时，Sun的J2EE版本已经升级到了1.4版，其中三个关键组件的版本也演进到了Servlet 2.4、JSP 2.0和EJB 2.1。至此，J2EE体系及相关的软件产品已经成为了Web服务端开发的一个强有力的支撑环境。<br /><br />　 　和J2EE不同的是，Microsoft的.NET平台是一个强调多语言间交互的通用运行环境。尽管.NET的设计者试图以.NET平台作为绝大多数Windows应用的首选运行环境，但.NET首先吸引的却是Web开发者的目光。2001年，ECMA通过了Microsoft提交的C#语言和CLI标准，这两个技术标准构成了.NET平台的基石，它们也于2003年成为了ISO的国际标准。2002年，Microsoft正式发布.NET Framework和Visual Studio .NET开发环境。早在.NET发布之前，就已经有许多Windows平台的Web开发者迫不及待地利用Beta版本开发Web应用了。这大概是因为，.NET平台及相关的开发环境不但为Web服务端应用提供了一个支持多种语言的、通用的运行平台，而且还引入了ASP.NET这样一种全新的Web开发技术。ASP.NET超越了ASP的局限，可以使用VB.NET、C#等编译型语言，支持Web Form、.NET Server Control、ADO.NET等高级特性。客观地讲，.NET平台，尤其是.NET平台中的ASP.NET的确不失为Web开发技术在Windows平台上的一个集大成者。<br /><br />　　<strong>XML语言及相关技术</strong><br /><br />　 　如果说HTML语言给Web世界赋予了无限生机的话，那么，XML语言的出现大概就可以算成是Web的一次新生了。按照Tim Berners-Lee的说法，Web是一个"信息空间"。HTML语言具有较强的表现力，但也存在结构过于灵活、语法不规范的弱点。当信息都以HTML语言的面貌出现时，Web这个信息空间是杂乱无章、没有秩序的。为了让Web世界里的所有信息都有章可循、有法可依，我们需要一种更为规范、更能够体现信息特点的语言。<br /><br />　 　1996年，W3C在SGML语言的基础上，提出了XML（Extensible Markup Language）语言草案。1998年，W3C正式发布了XML 1.0标准。XML语言对信息的格式和表达方法做了最大程度的规范，应用软件可以按照统一的方式处理所有XML信息。这样一来，信息在整个Web世界里的共享和交换就有了技术上的保障。HTML语言关心的是信息的表现形式，而XML语言关心的是信息本身的格式和数据内容。从这个意义上说，XML语言不但可以将客户端的信息展现技术提高到一个新的层次，而且可以显著提高服务端的信息获取、生成、发布和共享能力。为了将XML信息转换为HTML等不同的信息展现形式，1999年，W3C制定出了XSLT标准。同一年，IE 5.0增加了对XML和XSLT的支持。<br /><br />　 　现在，网站的开发者可以直接使用XML语言发布信息了。针对不同的应用领域，人们还制定了许多专门的XML规范。例如，2001年W3C发布的SVG（Scalable Vector Graphics）1.0标准就是一种用XML语言表达的、全新的二维矢量图形格式。开发者可以用SVG格式描述大多数已有的Flash动画。与Flash格式相比，符合XML标准的SVG格式显然更有利于信息交换和共享。<br /><br />　 　Web本身就是一个最大的分布式应用系统。对于分布式开发而言，XML技术也大有用武之地。一个明显的事实是，如果能让分布式应用借助XML格式交换信息，那么，以往横亘在分布式架构上的信息交换难题也就迎刃而解了。1999年，W3C和相关的企业开始讨论设计基于XML的通信协议，2000年，W3C发布SOAP（Simple Object Access Protocol）协议的1.1版。人们把利用SOAP协议传递XML信息的分布式应用模型称为Web Service。2001年，W3C发布了WSDL（Web Services Description Language）协议的1.1版。SOAP协议和WSDL协议共同构成了Web Service的基础。随后，J2EE和.NET这两大企业级开发平台先后实现了Web Service，并将其视为平台的一项核心功能。<br /><br />　 　Web Service对于Web开发者的重要意义在于，当我们需要在不同的服务端、不同的客户端乃至不同的应用类型、不同的计算设备之间传递信息的时候，以往的分布式开发技术或者因为适应性不强，或者因为扩展能力不足，都难以满足现代Web开发的需要，而Web Service正好填补了这一空白。<br /><br />　　<strong>Web开发框架和应用模型</strong><br /><br />　 　2000年以后，随着Web应用的日益复杂，人们逐渐意识到，单纯依靠某种技术多半无法达到快速开发、快速验证和快速部署的最佳境界。研究者开始尝试着将已有的Web开发技术综合起来，形成完整的开发框架或应用模型，并以此来满足各种复杂的应用需求。<br /><br />　 　Microsoft在客户端的技术集成方面走在了最前面。1998年时Microsoft推出的Windows 98就可以在桌面上集成Web页面，这实际上是将资源管理器和Web浏览器的功能有效地结合了起来。2000年后，Microsoft陆续推出了MSN Explorer和与之相关的MSN在线服务。这一应用模型将Web浏览、视频点播、邮件处理、网上游戏、在线聊天等许多种用户常用的Web功能集成在了一个统一的界面中。从信息利用的角度看，MSN试图让用户在一个最舒适的环境中获取足够的信息，这种努力的确值得人们称道。另一个与客户端技术集成相关的例子是搜索引擎Google在2003年展示给大家的Google工具栏功能。虽然Google工具栏有炒作和广告的嫌疑，但安装Google工具栏之后的IE浏览器将信息浏览和信息检索有机地结合了起来，这种小小的功能改进确实是对用户的体贴和帮助。<br /><br />　 　在Web服务端，2000年以后出现了几种主要的技术融合方式。首先，越来越多的Web开发环境开始支持MVC（Model-View-Contorller）的设计模型，为开发者提供了全套的开发框架。实际上，J2EE和.NET平台本身就是这种开发框架的典型代表。其次，门户服务（Portal Server）和Web内容管理（Web Content Management）在最近几年里成为了应用集成的重点模型。这两种应用模型可以直接为开发者或最终用户提供构建Web应用的高级平台，可以让Web开发和信息发布工作大为简化。在商业软件领域，这一类应用的例子包括Microsoft的SharePoint、IBM的WebSphere Portal、FileNet的Web Content Manager等等。开源项目在Web开发框架和应用模型方面表现得非常积极，Struts、Jetspeed、jPortlet、Cocoon、Lenya、XOOPS等都是开源世界里与MVC开发框架、门户服务和Web内容管理相关的优秀解决方案。<br /><br />　 　当然，技术集成绝不等于技术堆砌。一些Web站点和Web应用的开发者把XML语言、MVC框架等时髦技术拼凑起来，却不管它们是否能适应具体的应用环境，结果，他们的系统要么运行效率低下，要么功能残缺不全。反之，一个值得注意的事实是，像新浪、搜狐或网易这样的门户网站，在他们的信息发布页面（如新闻页面）里，尽管信息内容时刻都在刷新，但Web服务器上存放的始终都是静态的HTML页面。这种"落后技术"的优点是，在大量并发访问的情况下，门户网站的响应速度仍然很快。深入到技术层面，我们通常会惊讶地发现，这些网站使用的大多是自行研发的Web内容管理系统。当网站的内容编辑提交新的信息时，系统会自动将信息转换为HTML格式，发布到Web服务器集群的每一个结点上。在新浪网的一个角落里，我们可以找到"新浪网站发布系统"的研发历程：<br /><br />　　V 1.0（1997）：基于文件的版本，实现新闻首页、正文和专题的发布。<br />　　V 1.1（1998/12）：采用数据库后台、实现跨服务器发布，自动化程度高。<br />　　V 2.0（1999/3）：创立模版和域的全新概念，奠定了该系列的基本设计思路。<br />　　V 2.1（1999/9）：增加周边模块，如搜索、自动采集。<br />　　V 3.0（2000/1）：优化传输方式，增加相关新闻和评论。<br />　　V 3C（2000/6）：V3.0的编译版，也是商业版的原型。<br />　　V 3.1（2000/7）：优化数据库结构，采用内存CACHE大幅提速，增加了集中监控功能。<br />　　V 3.1C（2000/8）：商业用测试版本。<br />　　V 3.2（正在制作中）：重点解决备份系统的自动化切换，在机制上实现永不宕机。 <br /><br />　　这一份有趣的历史记录再一次印证了我关于Web开发技术的基本观点：一种技术只要能为用户提供高水平的信息服务，它就是最好、最先进的技术。<br /><br />　　 <strong>Web开发技术的未来</strong><br /><br />　　所有人都在关心Web的发展前景，所有人都想知道十年以后的Web会长成什么样子。要回答这些问题，没有谁比W3C更有权威了。W3C明确地告诉我们，Web的未来是语义化的Web（Semantic Web）。今天的Web可以自如地生成、传递和展现各式各样的信息，但它还只是一个信息的"容器"，很难揭示出信息本身的内容和特性。与此相对的是，未来的语义化Web是一种懂得信息内容的Web，是真正的"信息管理员"。<br /><br />　　从技术角度看，XML语言统一了信息的表达方式，但这离揭示信息内容的目标还相距甚远。1998年，W3C和一些研究机构开始对元数据（Metadata）进行研究。元数据是描述数据的数据，可以揭示信息的内容特性。1999年，NetScape提出的RSS（Rich Site Summary）建议标准是用元数据技术描述新闻等信息内容的第一次尝试。1999年，W3C的研究小组提出了RDF（Resource Description Framework）标准草案。RDF在XML语法的基础上，规定了元数据的存储结构和相关的技术标准。使用RDF语言，我们可以用统一的、可交换的格式揭示出信息本身的各种特性。2001年，W3C又开始着手制定OWL（OWL Web Ontology Language）标准。OWL语言也是一种符合XML标准的语言，它比RDF又前进了一步，可以更加深入、细致地描述信息内容。在RDF和OWL语言的帮助下，我们能让Web上的信息内容变得更容易理解、更便于交换和共享。2003年，W3C成立了语义化Web Service研究小组（Semantic Web Services Interest Group），研究在Web Service中加入语义技术的相关问题。2004年2月，W3C宣布RDF和OWL标准正式成为W3C的建议方案，这标志着语义化Web的大厦已经破土动工。<br /><br />　　随着语义化Web的诞生和发展，Web开发技术也必将经历更为重大的变革。可以预见的是，在未来的几年里，还会有许多新的开发技术或开发平台出现。从静态技术到动态技术，从开发平台到应用模型，从传统Web到语义化Web……为了让更多的人获得更有价值的信息服务，Web开发者们也许还会经历一次又一次的技术浪潮，还会面临更为严峻的技术挑战，但这和信息共享的最高目标相比，又算得了什么呢？</span>
		</span>
<img src ="http://www.blogjava.net/xine/aggbug/49724.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xine/" target="_blank">【Xine】中文站</a> 2006-06-01 17:20 <a href="http://www.blogjava.net/xine/articles/49724.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈谈Unicode编码</title><link>http://www.blogjava.net/xine/articles/49719.html</link><dc:creator>【Xine】中文站</dc:creator><author>【Xine】中文站</author><pubDate>Thu, 01 Jun 2006 09:18:00 GMT</pubDate><guid>http://www.blogjava.net/xine/articles/49719.html</guid><wfw:comment>http://www.blogjava.net/xine/comments/49719.html</wfw:comment><comments>http://www.blogjava.net/xine/articles/49719.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xine/comments/commentRss/49719.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xine/services/trackbacks/49719.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td style="FONT-SIZE: 12pt">
										<p>
												<br />
												<font size="2">这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念，增进知识，类似于打RPG游戏的升级。整理这篇文章的动机是两个问题：</font>
										</p>
										<dl>
												<dt>
														<font size="2">问题一： </font>
												</dt>
												<dd>
														<p>
																<font size="2">使用Windows记事本的“另存为”，可以在GBK、Unicode、Unicode big endian和UTF-8这几种编码方式间相互转换。同样是txt文件，Windows是怎样识别编码方式的呢？</font>
														</p>
														<p>
																<font size="2">我很早前就发现Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节，分别是FF、FE（Unicode）,FE、FF（Unicode big endian）,EF、BB、BF（UTF-8）。但这些标记是基于什么标准呢？</font>
														</p>
												</dd>
												<dt>
														<font size="2">问题二： </font>
												</dt>
												<dd>
														<font size="2">最近在网上看到一个ConvertUTF.c，实现了UTF-32、UTF-16和UTF-8这三种编码方式的相互转换。对于Unicode(UCS2)、GBK、UTF-8这些编码方式，我原来就了解。但这个程序让我有些糊涂，想不起来UTF-16和UCS2有什么关系。 </font>
												</dd>
										</dl>
										<p>
												<font size="2">查了查相关资料，总算将这些问题弄清楚了，顺带也了解了一些Unicode的细节。写成一篇文章，送给有过类似疑问的朋友。本文在写作时尽量做到通俗易懂，但要求读者知道什么是字节，什么是十六进制。</font>
										</p>
										<h3>0、big endian和little endian</h3>
										<p>
												<font size="2">big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时，究竟是将6C写在前面，还是将49写在前面？如果将6C写在前面，就是big endian。还是将49写在前面，就是little endian。</font>
										</p>
										<p>
												<font size="2">“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开，由此曾发生过六次叛乱，其中一个皇帝送了命，另一个丢了王位。</font>
										</p>
										<p>
												<font size="2">我们一般将endian翻译成“字节序”，将big endian和little endian称作“大尾”和“小尾”。</font>
										</p>
										<h3>1、字符编码、内码，顺带介绍汉字编码</h3>
										<p>
												<font size="2">字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码，为了处理汉字，程序员设计了用于简体中文的GB2312和用于繁体中文的big5。</font>
										</p>
										<p>
												<font size="2">GB2312(1980年)一共收录了7445个字符，包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7，低字节从A1-FE，占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。</font>
										</p>
										<p>
												<font size="2">GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号，它分为汉字区和图形符号区。汉字区包括21003个字符。2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字，同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。现在的PC平台必须支持GB18030，对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。</font>
										</p>
										<p>
												<font size="2">从ASCII、GB2312、GBK到GB18030，这些编码方法是向下兼容的，即同一个字符在这些方案中总是有相同的编码，后面的标准支持更多的字符。在这些编码中，英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼，GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。</font>
										</p>
										<p>
												<font size="2">有的中文Windows的缺省内码还是GBK，可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符，普通人是很难用到的，通常我们还是用GBK指代中文Windows内码。</font>
										</p>
										<p>
												<font size="2">这里还有一些细节：</font>
										</p>
										<ul>
												<li>
														<p>
																<font size="2">GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。</font>
														</p>
												</li>
												<li>
														<p>
																<font size="2">在DBCS中，GB内码的存储格式始终是big endian，即高位在前。</font>
														</p>
												</li>
												<li>
														<p>
																<font size="2">GB2312的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析：在读取DBCS字符流时，只要遇到高位为1的字节，就可以将下两个字节作为一个双字节编码，而不用管低字节的高位是什么。</font>
														</p>
												</li>
										</ul>
										<h3>2、Unicode、UCS和UTF</h3>
										<p>
												<font size="2">前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容（更准确地说，是与ISO-8859-1兼容），与GB码不兼容。例如“汉”字的Unicode编码是6C49，而GB码是BABA。</font>
										</p>
										<p>
												<font size="2">Unicode也是一种字符编码方法，不过它是由国际组织设计，可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set"，简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。</font>
										</p>
										<p>
												<font size="2">根据维基百科全书(<a href="http://zh.wikipedia.org/wiki/)的记载：历史上存在两个试图独立设计Unicode的组织，即国际标准化组织（ISO）和一个软件制造商的协会（unicode.org）。ISO开发了ISO" target="_blank" 10646项目，unicode协会开发了unicode项目。=""><font color="#000000">http://zh.wikipedia.org/wiki/)的记载：历史上存在两个试图独立设计Unicode的组织，即国际标准化组织（ISO）和一个软件制造商的协会（unicode.org）。ISO开发了ISO 10646项目，Unicode协会开发了Unicode项目。</font></a></font>
										</p>
										<p>
												<font size="2">在1991年前后，双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果，并为创立一个单一编码表而协同工作。从Unicode2.0开始，Unicode项目采用了与ISO 10646-1相同的字库和字码。</font>
										</p>
										<p>
												<font size="2">目前两个项目仍都存在，并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是10646-3:2003。</font>
										</p>
										<p>
												<font size="2">UCS规定了怎么用多个字节表示各种文字。怎样传输这些编码，是由UTF(UCS Transformation Format)规范规定的，常见的UTF规范包括UTF-8、UTF-7、UTF-16。</font>
										</p>
										<p>
												<font size="2">IETF的RFC2781和RFC3629以RFC的一贯风格，清晰、明快又不失严谨地描述了UTF-16和UTF-8的编码方法。我总是记不得IETF是Internet Engineering Task Force的缩写。但IETF负责维护的RFC是Internet上一切规范的基础。</font>
										</p>
										<h3>3、UCS-2、UCS-4、BMP</h3>
										<br />
										<br />
										<br />
										<p>
												<font size="2">UCS有两种格式：UCS-2和UCS-4。顾名思义，UCS-2就是用两个字节编码，UCS-4就是用4个字节（实际上只用了31位，最高位必须为0）编码。下面让我们做一些简单的数学游戏：</font>
										</p>
										<p>
												<font size="2">UCS-2有2^16=65536个码位，UCS-4有2^31=2147483648个码位。</font>
										</p>
										<p>
												<font size="2">UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows)，每行包含256个cells。当然同一行的cells只是最后一个字节不同，其余都相同。</font>
										</p>
										<p>
												<font size="2">group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中，高两个字节为0的码位被称作BMP。</font>
										</p>
										<p>
												<font size="2">将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节，就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。</font>
										</p>
										<h3>4、UTF编码</h3>
										<p>
										</p>
										<p>
												<font size="2">UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下：</font>
										</p>
										<table width="75%" border="1">
												<tbody>
														<tr>
																<td>
																		<font size="2">UCS-2编码(16进制)</font>
																</td>
																<td>
																		<font size="2">UTF-8 字节流(二进制)</font>
																</td>
														</tr>
														<tr>
																<td>
																		<font size="2">0000 - 007F</font>
																</td>
																<td>
																		<font size="2">0xxxxxxx</font>
																</td>
														</tr>
														<tr>
																<td>
																		<font size="2">0080 - 07FF</font>
																</td>
																<td>
																		<font size="2">110xxxxx 10xxxxxx</font>
																</td>
														</tr>
														<tr>
																<td>
																		<font size="2">0800 - FFFF</font>
																</td>
																<td>
																		<font size="2">1110xxxx 10xxxxxx 10xxxxxx</font>
																</td>
														</tr>
												</tbody>
										</table>
										<p>
												<font size="2">例如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间，所以肯定要用3字节模板了：<font color="#0000ff">1110</font>xxxx <font color="#0000ff">10</font>xxxxxx <font color="#0000ff">10</font>xxxxxx。将6C49写成二进制是：0110 110001 001001， 用这个比特流依次代替模板中的x，得到：<font color="#0000ff">1110</font>0110 <font color="#0000ff">10</font>110001 <font color="#0000ff">10</font>001001，即E6 B1 89。</font>
										</p>
										<p>
												<font size="2">读者可以用记事本测试一下我们的编码是否正确。</font>
										</p>
										<p>
												<font size="2">UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码，UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码，定义了一个算法。不过由于实际使用的UCS2，或者UCS4的BMP必然小于0x10000，所以就目前而言，可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案，UTF-16却要用于实际的传输，所以就不得不考虑字节序的问题。</font>
										</p>
										<h3>5、UTF的字节序和BOM</h3>
										<p>
												<font size="2">UTF-8以字节为编码单元，没有字节序的问题。UTF-16以两个字节为编码单元，在解释一个UTF-16文本前，首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E，“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”，那么这是“奎”还是“乙”？</font>
										</p>
										<p>
												<font size="2">Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表，而是Byte Order Mark。BOM是一个有点小聪明的想法：</font>
										</p>
										<p>
												<font size="2">在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符，它的编码是FEFF。而FFFE在UCS中是不存在的字符，所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前，先传输字符"ZERO WIDTH NO-BREAK SPACE"。</font>
										</p>
										<p>
												<font size="2">这样如果接收者收到FEFF，就表明这个字节流是Big-Endian的；如果收到FFFE，就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。</font>
										</p>
										<p>
												<font size="2">UTF-8不需要BOM来表明字节顺序，但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF（读者可以用我们前面介绍的编码方法验证一下）。所以如果接收者收到以EF BB BF开头的字节流，就知道这是UTF-8编码了。</font>
										</p>
										<p>
												<font size="2">Windows就是使用BOM来标记文本文件的编码方式的。</font>
										</p>
										<h3>6、进一步的参考资料</h3>
										<p>
												<font size="2">本文主要参考的资料是 "Short overview of ISO-IEC 10646 and Unicode" (<a href="http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。" target="_blank"><font color="#000000">http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。</font></a></font>
										</p>
										<p>
												<font size="2">我还找了两篇看上去不错的资料，不过因为我开始的疑问都找到了答案，所以就没有看：</font>
										</p>
										<ol>
												<li>
														<font size="2">"Understanding Unicode A general introduction to the Unicode Standard" (<a href="http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter04a)" target="_blank"><font color="#000000">http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter04a) </font></a></font>
												</li>
												<li>
														<font size="2">"Character set encoding basics Understanding character set encodings and legacy encodings" (<a href="http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter03)" target="_blank"><font color="#000000">http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter03) </font></a></font>
												</li>
										</ol>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/xine/aggbug/49719.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xine/" target="_blank">【Xine】中文站</a> 2006-06-01 17:18 <a href="http://www.blogjava.net/xine/articles/49719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>