1、字节序:缺省情况下,这两个类都使用了一种与CORBA兼容的方法处理字节序:发送端(将整型序列化成网络
字节串的一端)使用output_cdr <<
integer以本机字节序发送数据,而接收端(将网络字节串还原成整型的一端)需要判断一下送过来的字节序,先调用
input_cdr.reset_byte_order,然后再继续input_cdr >>
integer。也就是说,output_cdr的字节序是无法改变的,它总是以CDR_STREAM_BYTE_ORDER宏定义的方式发送数据。
而
这一情况可以改变。若编译ACE时,我们预定义了ACE_ENABLE_SWAP_ON_WRITE宏,则生成的dll代码中就允许在
output_cdr上调用reset_byte_order。这样,我们可以以任意的字节顺序向Remote机器发送字节串。在某些情况下,这是一种解
决问题的方法。比如:服务器很快,而客户机很烂时,可以考虑由服务器代替客户机处理字节序问题,而客户机只管收就行了。
2、内存对齐。在从ACE_InputCDR获得数据、向
ACE_OutputCDR输出数据时,若取消了宏ACE_LACKS_CDR_ALIGNMENT宏的定义,则在操作2、4、8、16位数据类型前(如
Long),则ACE总会调用ACE_OutputCDR::adjust (size_t size,size_t
align,char*& buf);或ACE_InputCDR::adjust (size_t size, size_t align,
char*&
buf);方法将数据对齐(分散)到align位置上,如4字节。这有利于提高数据访问速度,但是也带来一个问题。如:当我们使用
ACE_InputCDR执行以下代码时:
会莫名其妙地发现,实际ACE_InputCDR的rd_ptr向前走了不止上述字节数之和,而总是更多。同样,当使用ACE_OutputCDR向ACE_Message_Block写数据时,问题更为严重。我们执行完
若想当然地执行
结果几乎总是错的。这是因为ACE_OutputCDR实际写的字节数几乎总是比2+4+4+16+4+4多。我们若在上述语句后继续追加数据到ACE_Message_Block,则刚才写入的一部分数据就会被冲掉。这仍是因为自动字节对齐的原因。
当然,ACE_InputCDR和ACE_OutputCDR以同样的规则进行对齐,它们之间是一致的,关键是它们和ACE_Message_Block之间的配合容易出问题。
然后,我们根据返回值再对ACE_Message_Block的rd_ptr和wr_ptr进行调整。
需要注意的是,虽然ACE_InputCDR和ACE_OutputCDR可以这样创建:
ACE_InputCDR cdr(mb);//mb是一个ACE_Message_Block
ACE_OutputCDR cdr(mb);//mb是一个ACE_Message_Block
但是,当使用cdr向mb输入、输出数据后,mb的rd_ptr和wr_ptr指针并没有动!需要我们手工调整。
3、ACE_InputCDR cdr(mb);都干了些什么!
若你拥有一个复合消息,由mb指向头部,大致是这种情形:
那么,你执行下述语句
就会发现,cdr的 rd_ptr = = 0,(很正常啊),而cdr的wr_ptr = = 42。(没错是三个总和)。注意是ACE_InputCDR,因此,其wr_ptr仅仅起到边界作用,是无法向其追加数据的。
而reset调用了语句:
其中this->start_是ACE_InputCDR内部的一个 ACE_Data_Block对象的引用。而consolidate调用了以下语句:
也就是说,cdr内部的start_消息块的内容成了:
因此cdr的rd_ptr = = 0,而wr_ptr = = 42。就正常了。同时,我们还得到一条信息,就是对cdr的读取操作是跟原来mb没什么关系的。mb的rd_ptr从始致终没动地方。
ACE_OutputCDR::ACE_OutputCDR (ACE_Message_Block *mb,
也
就是说,ACE_OutputCDR
对象cdr的start_直接引用了mb的ACE_Data_Block。当我们向对象cdr输出字节串时实际直接写到了mb的数据区中。不过有件事情得
我们自己做:cdr写数据时,只更新自己对象的wr_ptr,而mb对象的wr_ptr得我们手动向后移。