使用ACE_CDR类进行网络编解码(5-2)

  ACE中提供了一组CDR类,专用于编解码,但它并不是专门针对我们在前面述情况的编解码情况,所以还必须进行定制。
我们下面也按照不同的方面来讨论如果定制及使用ACE的CDR类来做网络数据的编解码。
 
  ACE_InputCDR类负责解码,ACE_OutputCDR类负责编码。这两个类都提供流式操作,使用很方便。唯一不爽的是它不提供链式操作。
因为每一个“<<”或“>>”操作符重载函数返回的都是一个布尔变量,不像标准库那样返回表达式左值的引用。
 
  默认情况这两个类不对字节序进行任何转换,也就是总是使用主机字节序。如果两个主机间的字节序不一样,直接使用这两个类在一个
主机上编码,再在另一个主机上解码,就会导致出错。CNPv1第四章中的例子通过在每一个消息头前面增加一个布尔变量来指定编码时的
字节序,以解决这个问题。编码时首先把本地的主机字节序用一个布尔变量压进去,解码时首先解出这个布尔量,再用这个布尔量来设置
ACE_InputCDR的字节序。这样做又麻烦又容易出错。由其不便于异种系统之间的对接。最方便的方法也是通用的方法,就是编解码都使
用网络字节序,虽然会因为不必要的转换带来一点效率损失,但处理简单,也便于扩展。
 
  要指定编解码都使用网络字节序,我们可以通过在创建这两个类的对象时进行显示的指定,或是调用reset_byte_order方法
进行设置。以创建对象为例:

ACE_OutputCDR ocdr(&mb, ACE_CDR::BYTE_ORDER_BIG_ENDIAN);
ACE_InputCDR icdr(&mb, ACE_CDR::BYTE_ORDER_BIG_ENDIAN);

 
  对于ACE_OutputCDR类,第二个参数指定了要使用大端表示法对数据进行编码。对于ACE_InputCDR类,第二个参数指定了待
解码的数据是用大端表示法编码的。
 
  要注意的是,光有这样的指定还不够。缺省用ACE_OutputCDR进行编码时,它并不对写入的数据进行大小端转换,即使做了上述的指定。
 
  解决方法是,在编译ACE时,在config.h文件中加下下面的行。

#define ACE_ENABLE_SWAP_ON_WRITE

  这样就可以了。CDR类会自动的处理是否需要进行转换。
 
  还有一点要注意的,BYTE_ORDER_BIG_ENDIAN这个枚举在较早的的ACE版本中没有。5.6.5及以前版本中是没有的,5.6.7中有,
5.6.6我没有用过。如果你用的是较早版本,可以直接用硬编码的数字。

BYTE_ORDER_BIG_ENDIAN = 0;
BYTE_ORDER_LITTLE_ENDIAN = 1;

  
    这样我们就解决了字节序的问题。下面接着处理紧缩的问题。

作者: ronat   发布时间: 2010-10-25