当前位置: 首页 > news >正文

cdr序列化与反序列化

CDR(Common Data Representation)是 CORBA(Common Object Request Broker Architecture)中用于跨平台数据交换的二进制序列化格式。它解决了不同系统间(不同字节序、对齐方式)的数据兼容性问题。以下是 CDR 序列化和反序列化的详细解析:


CDR 核心特性

  1. 平台无关性
    • 自动处理字节序(大端/小端)
    • 处理数据对齐(如 4 字节对齐)
  2. 类型安全
    • 支持 CORBA IDL 定义的所有数据类型
  3. 无自描述性
    • 依赖 IDL 接口定义进行解析(无元数据)

CDR 序列化流程

以结构体 Person 为例:

// IDL 定义
struct Person {long id;      // 4 字节整数string name;  // 变长字符串
};
序列化步骤
  1. 写字节序标志(1 字节)

    • 0x00 表示大端序,0x01 表示小端序
  2. 序列化 id(4 字节整数)

    • 按字节序写入(如 id=4487 → 大端序 0x00 0x00 0x11 0x87
  3. 序列化字符串 name

    • 先写长度(4 字节无符号长整型)
      • "Alice" → 长度 50x00 0x00 0x00 0x05
    • 再写字符串内容(含结束符 \0
      • A l i c e \00x41 0x6C 0x69 0x63 0x65 0x00
    • 填充对齐:总长度按 4 字节对齐
      • 示例:6 字节内容 → 填充 2 字节 → 0x00 0x00
  4. 最终字节流(大端序示例):

| 字节序 | id (4B)   | 长度 (4B) | 字符串内容 (6B) | 填充 (2B) |
|--------|-----------|-----------|-----------------|-----------|
| 0x00   | 00 00 11 87 | 00 00 00 05 | 41 6C 69 63 65 00 | 00 00     |

CDR 反序列化流程

  1. 读字节序标志

    • 检测 0x00/0x01,决定后续解析方式
  2. 反序列化 id

    • 读取 4 字节 → 按字节序转换 → 0x00001187 = 4487
  3. 反序列化字符串

    • 读长度(4 字节)→ 5
    • 读内容(5+1 字节)→ "Alice\0"
    • 跳过填充字节(2 字节)

字节序处理机制

// 序列化时的伪代码
void serialize_long(long value, CDRStream& stream) {if (stream.is_big_endian()) {write_bytes(htobe32(value));  // 转大端序} else {write_bytes(htole32(value));  // 转小端序}
}// 反序列化时的伪代码
long deserialize_long(CDRStream& stream) {bytes = read_bytes(4);if (stream.is_big_endian()) {return be32toh(bytes);  // 大端转主机序} else {return le32toh(bytes);  // 小端转主机序}
}

对齐规则

CDR 要求数据按类型自然边界对齐:

数据类型对齐要求
char1 字节
short2 字节
long/float4 字节
double8 字节
string/sequence4 字节(长度域)

示例
序列化 short + long 时:

short s = 0x1234;
long  l = 0x56789ABC;

内存布局(小端序 + 2 字节填充):

| s (2B) | 填充 (2B) | l (4B)       |
|--------|-----------|--------------|
| 34 12  | 00 00     | BC 9A 78 56  |

CDR 使用场景

  1. CORBA 远程调用
    • 参数传递和返回值序列化
  2. DDS(Data Distribution Service)
    • 实时系统中的数据发布/订阅
  3. 金融交易系统
    • 交易所间的低延迟数据交换
  4. 航空电子系统
    • ARINC 653 标准中的进程间通信

CDR 优缺点

优点缺点
零解析开销(直接内存映射)无自描述性(需 IDL 定义)
自动处理跨平台差异不支持动态模式演化
支持复杂类型(联合体、序列)二进制格式难以人工调试

💡 替代方案对比

  • Protocol Buffers:自描述、支持版本演化,但需要运行时解析
  • JSON/XML:可读性好,但序列化开销大

实战示例(C++ 使用 ACE_CDR)

#include <ace/CDR_Stream.h>// 序列化
Person person{4487, "Alice"};
ACE_OutputCDR output;
output << person.id << person.name;
ACE_Message_Block* mb = output.begin();  // 获取CDR字节流// 反序列化
ACE_InputCDR input(mb);
long id;
ACE_CDR::Char* name;
input >> id >> name;  // 自动处理字节序

通过 CDR 的标准化序列化机制,CORBA 实现了真正的跨平台对象通信,成为分布式系统的基石技术之一。

示例

下面是一个详细的小端序 CDR(Common Data Representation)序列化示例,展示如何在小端序系统上序列化和反序列化数据。我们将使用一个包含多种数据类型的结构体进行演示。


示例结构体定义(IDL)

struct SensorData {unsigned short sensorId;  // 2 字节float temperature;       // 4 字节string location;         // 变长字符串
};

要序列化的数据:

  • sensorId = 0x1234(十进制 4660)
  • temperature = 25.5(浮点数)
  • location = "Lab"(字符串)

步骤 1:小端序 CDR 序列化

在小端序系统中(如 x86 CPU),数据低位字节存储在低地址:

序列化流程
  1. 字节序标志:写入 0x01(表示小端序)
  2. sensorId (2 字节)
    • 原始值:0x1234
    • 小端序:0x340x12
  3. 填充字节:因下个字段是 4 字节 float,需 2 字节填充
  4. temperature (4 字节)
    • 25.5 的 IEEE 754 表示:0x41CC0000
    • 小端序:0x000x000xCC0x41
  5. location 字符串
    • 长度(4 字节):"Lab" = 3 字符 + 1 终止符 → 长度=4 → 0x04000000(小端序)
    • 内容:L(0x4C), a(0x61), b(0x62), \0(0x00)
    • 填充:4 字节内容后无需填充(已是 4 字节对齐)
完整字节流(低地址 → 高地址):
| 字段        | 值 (十六进制)                 | 说明                     |
|-------------|-------------------------------|--------------------------|
| 字节序标志  | 01                            | 小端序标识               |
| sensorId    | 34 12                         | 低位在前                 |
| 填充        | 00 00                         | 对齐下一个4字节字段      |
| temperature | 00 00 CC 41                   | 浮点数字节逆序           |
| 字符串长度  | 04 00 00 00                   | 长度=4 (小端序)          |
| 字符串内容  | 4C 61 62 00                   | "Lab\0"                 |

可视化内存布局

低地址 → 高地址
01 34 12 00 00 00 00 CC 41 04 00 00 00 4C 61 62 00

步骤 2:小端序 CDR 反序列化

当接收方(小端序系统)读取此字节流时:

  1. 读字节序标志0x01 → 确认小端序
  2. 读 sensorId
    • 取 2 字节:0x34 0x12
    • 按小端序解析:0x1234 = 4660
  3. 跳过填充:忽略 2 字节 0x00 0x00
  4. 读 temperature
    • 取 4 字节:0x00 0x00 0xCC 0x41
    • 按小端序重组:0x41CC0000 → 25.5
  5. 读字符串
    • 读长度(4 字节):0x04 0x00 0x00 0x00 → 小端序 = 4
    • 读 4 字节内容:0x4C 0x61 0x62 0x00 → “Lab”

关键机制解析

1. 字节序自动处理
// 伪代码:小端序序列化float
void serialize_float(float value, CDRStream& stream) {uint32_t intRep = *(uint32_t*)&value; // 二进制表示if (stream.is_little_endian()) {write_bytes(intRep); // 直接写入(小端系统)} else {write_bytes(swap_bytes(intRep)); // 大端需转换}
}
2. 对齐填充规则
偏移字段大小对齐要求操作
0字节序标志1-写入 0x01
1sensorId22直接写入
3<填充>24填充 0x0000
5temperature44写入浮点
9字符串长度44直接写入
13字符串内容41写入+无填充
3. 字符串处理
// 字符串序列化伪代码
void serialize_string(string s, CDRStream& stream) {uint32_t len = s.length() + 1; // 包含 \0serialize_uint32(len);         // 写长度(小端序)write_bytes(s.c_str(), len);   // 写原始字符// 4字节对齐填充 (字符数据无额外填充)
}

小端序 vs 大端序 CDR 对比

同一数据 SensorData{4660, 25.5, "Lab"} 的差异:

字节序CDR 字节流(十六进制)
小端序01 34 12 00 00 00 00 CC 41 04 00 00 00 4C 61 62 00
大端序00 12 34 00 00 41 CC 00 00 00 00 00 04 4C 61 62 00

差异说明:

  1. 字节序标志不同(0x01 vs 0x00
  2. 数值字段字节逆序:
    • sensorId: 34 12 vs 12 34
    • temperature: 00 00 CC 41 vs 41 CC 00 00
  3. 长度字段:04 00 00 00 vs 00 00 00 04

实际应用场景

  1. 嵌入式系统通信(ARM Cortex-M 小端设备)

    // 发送端(小端系统)
    SensorData data = {0x1234, 25.5, "Lab"};
    CDR_serialize(&output_stream, data); // 直接内存拷贝// 接收端(同为小端系统)
    CDR_deserialize(&input_stream, &data); // 零转换开销
    
  2. 混合字节序环境(需显式转换)

    // 接收方是大端系统(如 PowerPC)
    CDRStream stream = receive_network_data();
    if (stream.endian_flag == 0x01) { // 检测到小端数据convert_cdr_to_host_order(&stream); // 字节序转换
    }
    deserialize(&stream, &data);
    

重要注意事项

  1. 字节序标志位置:始终是 CDR 流的第一个字节
  2. 嵌套结构处理:内部结构不添加额外字节序标志
  3. 浮点数兼容性:所有平台必须使用 IEEE 754 标准
  4. 数据对齐:即使在同字节序系统中,填充仍不可省略
  5. 性能优势:小端系统处理小端 CDR 时,可直接内存映射(零拷贝)

通过这个示例,您可以看到 CDR 如何在小端序系统中高效地处理数据序列化,同时保持跨平台兼容性。核心在于字节序标志和对齐规则的应用,使得不同架构的设备能正确解析数据。

http://www.dtcms.com/a/283213.html

相关文章:

  • SenseGlove力反馈手套:医疗、生产制造、军事模拟与远程机器人控制新革命
  • 【AI交叉】化学:人工智能如何重塑现代化学研究?
  • 谷歌引入开源全栈 AI 代理栈:借助 Gemini 2.5 和 LangGraph 实现多步网络搜索、反思与综合
  • NMS代码详解(数据维度变换解析)
  • 格密码--Ring-SIS和Ring-LWE
  • 架构解密|一步步打造高可用的 JOCR OCR 识别服务
  • oracle会话控制和存储状态查询
  • pyqt当中splitter.setSizes()不生效
  • C++中vector和list的优缺点对比以及deque
  • PowerJob集群机器数为0问题
  • Python第八章作业(初级)
  • 如何使用VScode使用ssh连接远程服务器不需要输入密码直接登录
  • 27.Hamming 距离
  • transformers基础Data Collator
  • 教程:如何快速查询 A 股实时 K线和5档盘口
  • 今日行情明日机会——20250716
  • Redis深度解析:从缓存到分布式系统的核心引擎
  • 用python实现自动化布尔盲注
  • pytest--1--pytest-mock常用的方法
  • 代码随想录day36dp4
  • 震坤行获取商品SKU操作详解
  • 16路串口光纤通信FPGA项目实现指南
  • Kotlin获取集合中的元素操作
  • Java与Vue精心打造资产设备管理系统,提供源码,适配移动端与后台管理,助力企业高效掌控资产动态,提升管理效能
  • 【Java】JUC并发(synchronized进阶、ReentrantLock可重入锁)
  • 二重循环:输入行数,打印直角三角形和倒直角三角形
  • Java后端开发核心笔记:分层架构、注解与面向对象精髓
  • 基于Android的旅游计划App
  • Web基础 -MYSQL
  • 冷库耗电高的原因,冷链运营者的降本增效的方法