锁定老帖子 主题:ICE 协议概要
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-09-01
1、ICE协议由三部分组成:<o:p></o:p> 1)数据编码规范,用来进行各种数据类型的序列化。<o:p></o:p> 2)客户端与服务器端的交互的消息类型,以及在何种情况下应发出何种消息的规范。<o:p></o:p> 3)客户端与服务器端如何协商二者所用协议及编码版本的规范。<o:p></o:p> 2、数据编码规范:<o:p></o:p> 1)数值类型的编码是little-endian(x86的都是这个,所以基本上不用管了,除非你用Mac...)。即0x12345678存放在内存中是0x78 0x56 0x34 0x12。<o:p></o:p> 2)size,数据长度(string)或者数据计数(sequence):若长度或计数小于255,则用一个byte来表示,如果大于等于255,则用1byte+1int(共五个byte)来表示,其中第一个byte值为255。即:若长度或者计数为254,则size为0xFE,若长度或者计数为256,则size为0xFF 0x01 0x00 0x00 0x00。<o:p></o:p> 3)数据封装:数据封装是指将某可变长度的未知数据及其相关信息(大小、编码版本等)打包成一个单元包。其结构如下:<o:p></o:p> struct Encapsulation {<o:p></o:p> int size; //整包的长度<o:p></o:p> byte major; //编码的主版本号<o:p></o:p> byte minor; //编码的次版本号<o:p></o:p> // [... size - 6 bytes ...] 数据,长度可为0(size值为6)<o:p></o:p> };<o:p></o:p> 4)Slices:考虑到Exception和Class到达接收端后,由于接收端仅理解其部分信息(比如只有父类型定义而无子类型定义),因此Exception和Class的编码也具有一定的层次性,每一个继承层次的数据编码叫做一个slice。每个slice由一个int型(slice的总size)+数据组成。接收端接收到数据进行解码时,可以通过slice的size,直接由当前的slice跳转定位到下一个slice。<o:p></o:p> 5)基本类型:<o:p></o:p> bool 1字节 1为true,0为false<o:p></o:p> byte 1 字节<o:p></o:p> short 2字节<o:p></o:p> int 4字节<o:p></o:p> long 8字节<o:p></o:p> float 4字节 IEEE标准 23位小数,8位指数,1位标志<o:p></o:p> double 8字节 IEEE标准 52位小数,11位指数,1位标志<o:p></o:p> 6)string 字符串:字符串由一个size和一串UTF-8编码的数据组成,size见2),字符串不是以NULL结束的。空字符串的size为0。<o:p></o:p> 7)sequence 序列:序列由一个size和一系列按各自类型编码的数据组成,size见2)。<o:p></o:p> 8)dictionary 字典: 字典由一个size和一系列键值对编码的数据组成,size见2),键值对是一个struct的数据结构,这个数据结构有两个成员,一个是key,一个是value。<o:p></o:p> 9)enumerator 枚举:枚举数据的编码是由其定义的枚举个数决定的,如果枚举个数在1-127之间,每个枚举值为一个byte,若个数在128-32767之间,其值为short,大于32767的,其值为int。<o:p></o:p> 10)structure 结构:结构中的每个元素,依次按各自的类型编码,按各自在声明中的位置排列。<o:p></o:p> 11)exception 异常:异常是由以下几部分组成:<o:p></o:p> Uses Classes (bool) 是否存在后面的Class instances<o:p></o:p> Type ID(string) Type ID和下面的Slice for members是一组的,一个Exception中可能存在多组。<o:p></o:p> //Slice for members……<o:p></o:p> //Class instances(optional) 指Exception引用或者间接引用的Class实例的编码。<o:p></o:p> 首先Exception第一个字节是一个bool类型,标志是否Exception包括有Class实例的编码,若有的话,在Exception的尾部会有Class实例的编码。紧接着是一系列的键值对,键为Type ID(string),值为Type ID所对应的member编码(slice)。这些键值对的排列顺序是按先子类后父类,每个slice中的member排列顺序是按其类定义中的顺序。接在键值对后面的是Class实例编码。<o:p></o:p> 举个例子,看下面这个Exception类层次(member后面括号中为假定值):<o:p></o:p> exception Base {<o:p></o:p> int baseInt; (99)<o:p></o:p> string baseString; (”Hello”<o:p></o:p> };<o:p></o:p> exception Derived extends Base{<o:p></o:p> bool derivedBool; (true)<o:p></o:p> string derivedString; (”World!”)<o:p></o:p> double derivedDouble;(3.14)<o:p></o:p> };<o:p></o:p> 其编码后的数据为:<o:p></o:p> 0x0 (不存在Class实例的引用)<o:p></o:p> 0x10 “::Derived” (Type Id string的长度及内容)<o:p></o:p> 0x14 0x00 0x00 0x00(slice的长度)<o:p></o:p> 0x1(derivedBool)<o:p></o:p> 0x7 “World!” (derivedString的长度及内容)<o:p></o:p> 3.14D (derivedDouble,占8字节)<o:p></o:p> 0x7 “::Base” (Type Id string的长度及内容)<o:p></o:p> 0x0E 0x00 0x00 0x00(slice的长度)<o:p></o:p> 0x99 0x00 0x00 0x00(baseInt)<o:p></o:p> 0x06 “Hello” (baseString的长度及内容)<o:p></o:p> 当接收端接收到这数据时,会首先取第一个字节,判断是否需要解码Class实例(上面这个例子没有),然后会检查第一个Type ID(::Derived)。如果接收端拥有这个Type的定义,则它会将其解码,如果接收端没有这个Type的定义,它可以根据Slice的长度size,跳过这个Type的Slice,处理下一个Type的Slice,直到所有的Type ID都处理完。如果接收端不识别所有的Type,则会抛出一个MarshalException异常(这种情况往往是由于Client和Server各自采用不同的定义文件造成的)。<o:p></o:p> 若Exception包括有Class实例的编码,其编码规则按Class的规则来处理。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 3507 次