深入理解 hessian 协议

来源:互联网 发布:qq飞车解封软件 编辑:程序博客网 时间:2024/06/08 12:00

hessain通过对数字进行紧凑压缩达到节省空间的目的,原理跟protobuf相似。都非常的巧妙

以下是从官网摘取的片段,,,刚开始看,有点费解,,,虽然知道很巧妙,但是不知道为什么要这么设计

计算器移位运算要好好做做功课

4.5.  int



Integer Grammar

int ::= 'I' b3 b2 b1 b0    ::= [x80-xbf]    ::= [xc0-xcf] b0    ::= [xd0-xd7] b1 b0
 Figure 11 

A 32-bit signed integer. An integer is represented by the octet x49 ('I') followed by the 4 octets of the integer in big-endian order.

value = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;



 TOC 

4.5.1.  Compact: single octet integers

Integers between -16 and 47 can be encoded by a single octet in the range x80 to xbf.

value = code - 0x90



 TOC 

4.5.2.  Compact: two octet integers

Integers between -2048 and 2047 can be encoded in two octets with the leading byte in the range xc0 to xcf.

value = ((code - 0xc8) << 8) + b0;



 TOC 

4.5.3.  Compact: three octet integers

Integers between -262144 and 262143 can be encoded in three bytes with the leading byte in the range xd0 to xd7.

value = ((code - 0xd4) << 16) + (b1 << 8) + b0;



 TOC 

4.5.4.  Integer Examples



x90                # 0x80                # -16xbf                # 47xc8 x00            # 0xc0 x00            # -2048xc7 x00            # -256xcf xff            # 2047xd4 x00 x00        # 0xd0 x00 x00        # -262144xd7 xff xff        # 262143I x00 x00 x00 x00  # 0I x00 x00 x01 x2c  # 300


我们上点基础吧

  • 移位运算能做什么

用移位实现乘除法运算,提高运行效率  用移位实现乘除法运算    
 a=a*4;     b=b/4;    可以改为:     a=a<<2;     b=b>>2;    
 说明:  
 除2 = 右移1位        
 乘2 = 左移1位 
 除4 = 右移2位               
 乘4 = 左移2位 
 除8 = 右移3位              
   
 乘8 = 左移3位 ...                                     
   ...     通常如果需要乘以或除以2的n次方,都可以用移位的方法代替。  
  大部分的C编译器,用移位的方法得到代码比调用乘除法子程序生成的代码效率高。 
  实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果,如:    a=a*9  分析a*9可以拆分成a*(8+1)即a*8+a*1, 因此可以改为:    a=(a<<3)+a a=a*7  
 分析a*7可以拆分成a*(8-1)即a*8-a*1, 因此可以改为:    a=(a<<3)-a 关于除法读者可以类推, 此略

  • 有了上面这些基础,稍微对左移有点认识,,,但是对正负数的位运算还是很迷糊

计算机对有符号数(包括浮点数)的表示有三种方法:原码、反码和补码, 补码=反码+1。在 二进制里,是用 0 和 1来表示正负的,最高位为符号位,最高位为 1 代表负数,最高位为 0 代表正数。

    以java中8位的byte为例,最大值为:0111 1111,最小值为1000 0001。

    那么根据十进制的数字,我们如何转换为二进制呢?对于正数我们直接转换即可,对于负数则有一个过程。

    以负数-5为例:

    1.先将-5的绝对值转换成二进制,即为0000 0101;

    2.然后求该二进制的反码,即为 1111 1010;

    3.最后将反码加1,即为:1111 1011

所以Java中Integer.toBinaryString(-5)结果为11111111111111111111111111111011. Integer是32位(bit)的.


以上的基础知识算是对移位运算的入门了,,,现在来分析下 hessain的int表示



4.5.1.  Compact: single octet integers

Integers between -16 and 47 can be encoded by a single octet in the range x80 to xbf.

value = code - 0x90


我们来理解下,  hessain的8bit 二进制高位不表示符号。 所以 

x80-xbf区间,可以表示为-16 到47 。   x80 = 128,x90=144 ,先减下就是 -16,最大值 xbf=191-x90=47



Integers between -2048 and 2047 can be encoded in two octets with the leading byte in the range xc0 to xcf.

Compact: two octet integers

value = ((code - 0xc8) << 8) + b0;


(xc0 到 xcf)_-0xc8的范围计算  :xc0=192,xcf=207,xc8=200, 因此 (xc0 到 xcf)_-0xc8的范围是 -8 - 7  

再乘以256(左移8位) = -2048- 1792 。   b0的范围是0-255,   ((code - 0xc8) << 8) + b0的范围是 -2048 - 2047


你有没有观察到,其实两个8bit表示的数字其实已经涵盖1个8bit表示的数字。当然,在编码的是如果数字范围是-16到47就用1个字节表示。 如果硬要用两个字节表示也是可以的。


现在你也许会有个疑问:当我拿到Ixc2 x56 (随便写个数字),到底表示的是1个8bit数字还是2个8bit数字呢?它的分界点在哪里呢?

int ::= 'I' b3 b2 b1 b0  

::= [x80-xbf]  

::= [xc0-xcf] b0  

::= [xd0-xd7] b1 b0

再看看这个,,, 你有没有发现,,左前缀是不重复的。如果第一个字节落在x80-xbf之间,就表示1个字节表示。如果落在xc0-xcf区间,就用2个字节表示,如果落在xd0-xd7,就用3个字节表示,,否则用4个字节表示。

那么,,这个设计是如何想出来的?这几个左前缀是如何考虑出来的?




参考 hessain官方文档

http://hessian.caucho.com/doc/hessian-serialization.html

位运算

http://wenku.baidu.com/view/34176f06bed5b9f3f90f1c16


0 0
原创粉丝点击