关于ACE_InputCDR和ACE_OutputCDR读写数据时的经验
2007-09-05 09:43
323 查看
正在处理您的请求...
MzForm |
|
StatusBar |
如果稍微不注意就会出现一些奇怪的字节错位的情况。 在这里我总结一下使用的规则: ACE_OutputCDR out(mb); out << ?? ; //这种方法简称out 例一: 如果out 了一个short再out一个long 字节将成为如下排列(16进制) xx xx ?? ?? xx xx xx xx 其中,问号部分即是因为在long写入时进行的按long长度对齐。该数据是无意义的 例二: 如果out了一个char再out一个 short 字节将成为如下排列 xx ?? xx xx 其中,问号部分即是因为在short写入时进行的按short长度对齐。该数据是无意义的 例三: 如果out了一个short再out一个char 字节将成为 4000 如下排列 xx xx xx 这里输入的char不会造成对齐问题,因为char只有一个字节(都是倍数) 例四: 如果out了一个short再out一个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 (); #endif /* ACE_LACKS_CDR_ALIGNMENT */ char *end = buf + size; if (end <= this->current_->end () && end >= buf) { #if !defined (ACE_LACKS_CDR_ALIGNMENT) this->current_alignment_ += offset + size; #endif /* ACE_LACKS_CDR_ALIGNMENT */ this->current_->wr_ptr (end); return 0; } return this->grow_and_adjust (size, align, buf); } 好!我们找到了,原来校正的代码就在这里!仔细看看 #if !defined (ACE_LACKS_CDR_ALIGNMENT) 这里说明,如果你定义了ACE_LACKS_CDR_ALIGNMENT,那么ACE就不会帮你校准对齐字节啦! 哈哈,是不是很兴奋?别着急,让我们动手 打开config.h文件,加入以下一句 #define ACE_LACKS_CDR_ALIGNMENT 重新编译ACE,好,将新的lib加入工程 (如果你用了aced.dll或ace.dll,注意路径,或把新的dll拷贝到system32目录下) 让我们来运行一下原来的程序 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 哈哈!你再试试以上四个例子,会发现都没有问题了! 那么,从现在开始,你还需要写自己的整编和解编的包装类吗?我看没有必要了吧。还不快动手修改你的工程? 补充: 如果不这么做。那么在接收端用ACE_IntputCDR进行 >> 操作时。如果没有进行读时的强制转换 比如 没有这样写 ACE_CDR::Char c; ACE_CDR::UShort s; ACE_InputCDR in(...); in >> (ACE_CDR::ULong)c; in >> (ACE_CDR::ULong)s; 而是这样写: ACE_InputCDR in(...); in >> c; in >> s; 必出各种字节乱码问题。因为中间多了CORBA的marshaling 与demarshaling对齐数据。 如果按照以上方法重新编译ACE后。即可省事多了(同时也节省了网络流量) ACE_OutputCDR out(..); out << c; out << s; ------------------------------------ ACE_InputCDR in(...); in >> c; in >> s; 无须任何类型转换。绝不出错。 再次声明。你不必自己写整编和解编。该论坛多次讨论过该问题。这是一个非常好的解决之道。 out << (ACE_CDR::UShort)1; out << (ACE_CDR::Long)2; ACE_LOG_MSG->log_hexdump( LM_DEBUG , mb->base() , out.length() , "t"); |
相关文章推荐
- 关于ACE_InputCDR和ACE_OutputCDR读写数据时的经验
- 关于ACE_InputCDR和ACE_OutputCDR读写数据时的经验
- 关于ACE_InputCDR和ACE_OutputCDR读写数据时的经验
- 关于ACE的InputCDR和OutputCDR读写数据
- C#编程中关于数据缓存的经验总结
- 一个项目的经验教训:关于打乱和拆分数据
- 一个项目的经验教训:关于打乱和拆分数据
- 关于PHP中Socket连接及读写数据超时的问题
- 【原创】DE2 CCD 中关于数据读写有效位的疑惑
- 关于使用cspreadsheet读写EXCEL表格数据的问题
- C#编程中关于数据缓存的经验总结一直以来,
- [资料] 经验分享——EEPROM读写及数据管理
- 关于STM8的用户数据空间读写问题
- 关于数据科学,书上不曾提及的三点经验
- ACE_Mesaage_Block,ACE_InputCdr,ACE_OutputCdr的使用
- 关于android手机设置项和数据缓存的一点经验
- 一个项目的经验教训:关于打乱和拆分数据
- 一个项目的经验教训:关于打乱和拆分数据
- 关于使用cspreadsheet读写EXCEL表格数据的问题
- 关于JSON数据的入门了解以及在java中简单的读写json文件