peakzhang 发表于 2008-1-14 21:09:39

npv1例子的疑惑

大家好 我刚开始学ACE 有个问题想请教一下
在第4章的loggingserver例子里
The Logging Service Message Framing Protocol 里面规定byteorder是4个字节
但是为什么cdr >> ACE_InputCDR::to_boolean (byte_order) 读的时候却是按bool来读的?难道ACE里bool占4个字节吗?
而后面直接读length, 这样没有问题吗,为什么指针不要跳3个字节?前面读byteorder的时候只读了1个字节阿?
24   ACE_CDR::ULong length;
25   cdr>>length;
请大家帮帮我 谢谢

peakzhang 发表于 2008-1-14 21:09:51

其实这句代码上面的注释,已经说明了,是先读取4个字节的char,再用to_boolean的方法,转换成bool类型来操作。至于传递的数据里面不用bool,是因为需要数据对齐的原因。
所以后面直接读length,不会有问题的。你可以调试一下代码就明白了。

peakzhang 发表于 2008-1-14 21:10:04

还是没弄明白 debug进去看了下

cdr >> ACE_InputCDR::to_boolean (byte_order)确实只读一个字节阿

并没有看到先读4个char

server:

    ACE_InputCDR cdr (payload);

    // Extract the byte-order and use helper methods to
    // disambiguate octet, booleans, and chars.
    ACE_CDR::Boolean byte_order;
    cdr >> ACE_InputCDR::to_boolean (byte_order);

client:

    ACE_OutputCDR header (ACE_CDR::MAX_ALIGNMENT + 8);
    header << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);

    // Store the size of the payload that follows
    header << ACE_CDR::ULong (length);

peakzhang 发表于 2008-1-14 21:10:28

我看的英文的 问题已经解决了

我深入debug了 ace在写和读数据之前对齐数据

假设内存起始地址为0,你要写的数据为 BYTE DWORD BYTE WORD BYTE DWORD

那么实际数据的存放位置为            0    4   9    10   12   16

也就是说你所存储的数据的地址会被ACE修改为数据类型大小的倍数

也就是说bytecode占一个字节,跳过3个字节,然后存放length, 总共还是占8个字节

书上并没有讲清楚,而且制定传输的数据大小的时候用了这样的写法

    ACE_OutputCDR header (ACE_CDR::MAX_ALIGNMENT + 8);
    header << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
    header << ACE_CDR::ULong (length);
    iovec iov;
    iov.iov_base = header.begin ()->rd_ptr ();
    iov.iov_len= 8;

很容易让人误解,以为bytecode和length各占4个字节,其实bytecode只占1个字节,中间的字节都跳过了

我觉得最好写成 iov.iov_len= header.totoal_length(); 更容易理解些

大家看例子的时候没有发现这个问题吗?希望我这个发现对大家会有帮助

bodyguard 发表于 2008-7-29 22:08:41

1:to_boolean 这里确实只读了1个字节
===============
to_boolean 是类ACE_InputCDR的内嵌的一个结构类型。
struct to_boolean
{


ACE_CDR::Boolean& ref;
   to_boolean(ACE_CDR::Boolean& in):ref(in){};
};

cdr >> ACE_InputCDR::to_boolean( in);//右边构造了一个匿名变量,其类型为ACE_InputCDR::to_boolean,该变量的成员ref是in的引用。
就是
cdr::operator >>(ACE_InputCDR::to_boolean(in));

或者说可以更啰嗦地写为:

ACE_InputCDR::to_boolean var(in);
cdr >> var;

2:接下来读ULONG
===================
ACE_CDR::Boolean
ACE_InputCDR::read_4 (ACE_CDR::ULong *x)
{
char *buf;
if (this->adjust (ACE_CDR::LONG_SIZE, buf) == 0)    //在读ULONG的4个字节前调用了adjust
    {
#if !defined (ACE_DISABLE_SWAP_ON_READ)
      if (!this->do_byte_swap_)
      *x = *reinterpret_cast<ACE_CDR::ULong*> (buf);
      else
      ACE_CDR::swap_4 (buf, reinterpret_cast<char*> (x));
#else
      *x = *reinterpret_cast<ACE_CDR::ULong*> (buf);
#endif /* ACE_DISABLE_SWAP_ON_READ */
      return true;
    }
this->good_bit_ = false;
return false;
}

CDR_BASE.h里定义了枚举 LONG_SIZE = 4
adjust做了什么?

ACE_INLINE int
ACE_InputCDR::adjust (size_t size,
                      size_t align,
                      char*& buf)
{
#if !defined (ACE_LACKS_CDR_ALIGNMENT)   //如果config.h里没有定义此宏,则需要调整读指针按align=4对齐
buf = ACE_ptr_align_binary (this->rd_ptr (), align);
#else
buf = this->rd_ptr ();                                 //如果config.h里定义了此宏,则不需要调整读指针
#endif /* ACE_LACKS_CDR_ALIGNMENT */
char *end = buf + size;
if (end <= this->wr_ptr ())
    {
      this->start_.rd_ptr (end);
      return 0;
    }
this->good_bit_ = false;
return -1;
#if defined (ACE_LACKS_CDR_ALIGNMENT)
ACE_UNUSED_ARG (align);
#endif /* ACE_LACKS_CDR_ALIGNMENT */
}

ACE_ptr_align_binary 是如何调整读指针的?
请看这里,调整后读指针的地址按alignment对齐!
OS_Memory.h:
#define ACE_align_binary(ptr, alignment) \
    ((ptr + ((ptrdiff_t)((alignment)-1))) & (~((ptrdiff_t)((alignment)-1))))
/// Return the next address aligned to a required boundary
#define ACE_ptr_align_binary(ptr, alignment) \
      ((char *) ACE_align_binary (((ptrdiff_t) (ptr)), (alignment)))

结论:
===
1:读ACE_CDR::Boolean时:确实只读了一个字节,读完后没有移动指针至ULONG的起始处。
2:读ACE_CDR::ULONG时:如没有定义宏ACE_LACKS_CDR_ALIGNMENT,读指针先向后移动至按4字节对齐,再读ULONG的4个字节。

[ 本帖最后由 bodyguard 于 2008-7-30 00:25 编辑 ]
页: [1]
查看完整版本: npv1例子的疑惑