2007年2月11日星期日

关于ACE_InputCDR和ACE_OutputCDR读写数据时的经验

我今天测试发现ACE_InputCDR ACE_OutputCDR并不是那么简单。

如果稍微不注意就会出现一些奇怪的字节错位的情况。

在这里我总结一下使用的规则:

         ACE_OutputCDR out(mb);

         out  << ?? ;     //这种方法简称out

         例一:

         如果 out 了一个shortout一个long

         out << (ACE_CDR::UShort)1;

         out << (ACE_CDR::Long)2;

         ACE_LOG_MSG->log_hexdump( LM_DEBUG , mb->base() , out.length() , "t");

         字节将成为如下排列(16 进制)            xx xx ?? ?? xx xx xx xx

         其中,问号部分即是因为在long 写入时进行的按long长度对齐。该数据是无意义的

        

         例二:

         如果out了一个 charout一个 short

         字节将成为如下排列             xx  ??  xx xx

         其中,问号部分即是因为在short写入时进行的按short 长度对齐。该数据是无意义的

        

        

         例三:

         如果out了一个 shortout一个char

         字节将成为如下排列             xx  xx    xx

         这里输入的char不会造成对齐问题,因为char 只有一个字节(都是倍数)

        

         例四:

         如果out了一个shortout 一个char out 一个 long

         字节将成为如下排列            xx  xx  xx  ??  xx  xx  xx  xx

        

         按照以上可总结出,每out一个类型的数据时,输出流将自动按照这个输入类型的长度序对齐,如果没有对齐,则自动填充。

     导致读数据时产生非常多的问题。(你不见CNPV1中都是强转成ACE_CDR::ULong吗?这下知道了吧)。

解决方案有两种:

方案一:全部一种类型吧!比如全部用ACE_CDR::ULong

    不过这种方法通常不适合实际的应用。让偶动物园墙垮来帮大家解决这个心结。:) 西西,请看下一方案。

方案二:

大家都会觉得这玩意被做出来怎么就不好用呢?没道理吧。我也觉得没道理,所以为了证实ACE开发者都是大牛,偶就把ACE的代码挖出来给大家看看,

看看这里到底有着什么样的玄机?

我们就拿ACE_ULong来开刀:

大家翻开CDR_Stream.inl文件,找到以下语句

ACE_INLINE ACE_CDR::Boolean
operator<< (ACE_OutputCDR &os, ACE_CDR::ULong x)
{
   os.write_ulong (x);
  return (ACE_CDR::Boolean) os.good_bit ();
}

继续下去 os.write_ulong (x);

ACE_INLINE ACE_CDR::Boolean
ACE_OutputCDR::write_ulong (ACE_CDR::ULong x)
{
  const void *temp = &x;
  return this->write_4 (reinterpret_cast<const ACE_CDR::ULong*> (temp));
}

继续跟踪this->write_4 (reinterpret_cast<const ACE_CDR::ULong*> (temp));

ACE_CDR::Boolean
ACE_OutputCDR::write_4 (const ACE_CDR::ULong *x)
{
  char *buf = 0;
  if (this->adjust (ACE_CDR::LONG_SIZE, buf) == 0)
    {

       ....

    }

}

再继续adjust (ACE_CDR::LONG_SIZE, buf)

ACE_INLINE int
ACE_OutputCDR::adjust (size_t size, char*& buf)
{
  return this->adjust (size, size, buf);
}

继续 this->adjust (size, size, buf);

ACE_INLINE int
ACE_OutputCDR::adjust (size_t size,
                       size_t align,
                       char*& buf)
{
  if (!this->current_is_writable_)
    return this->grow_and_adjust (size, align, buf);

#if !defined (ACE_LACKS_CDR_ALIGNMENT)
  const size_t offset =
    ACE_align_binary (this->current_alignment_, align)
    - this->current_alignment_;

  buf = this->current_->wr_ptr () + offset;
#else
  buf = this->current_->wr_ptr ();

没有评论: