自学内容网 自学内容网

Protobuf 的工作原理

在网络通信中,尤其是通过 protobuf(Protocol Buffers)这类序列化框架时,填充字节的影响内存对齐的操作是不同的。以下是关于如何使用 protobuf 处理数据以及如何减少传输的压力的解释:

1. Protobuf 的工作原理

Protocol Buffers 是一种高效的序列化格式,用于将数据结构转换为二进制格式以便于传输和存储。它的目标是减少数据传输和存储的开销。序列化时,protobuf 会将数据结构转换为一个紧凑的二进制表示,而不考虑数据在内存中的对齐和填充。

2. 填充字节和网络传输

填充字节 是编译器为了确保数据对齐而在结构体成员之间插入的额外字节。填充字节在网络传输中不会直接影响,因为数据在传输前需要被序列化成连续的二进制流。

3. Protobuf 如何处理填充字节

  • 序列化和反序列化protobuf 序列化过程会将数据结构转换为紧凑的二进制格式,不会包含额外的填充字节。每个字段都会按照其实际数据类型编码,避免了填充字节的影响。

  • 紧凑格式protobuf 使用了变长编码(如 Varint 编码)来表示整数,压缩数据并减少传输的数据量。对于每个字段,protobuf 只会编码实际的数据值,而不会考虑填充字节。

4. 示例

假设我们有一个结构体:

#include <stdio.h>
#include <stdint.h>
​
#pragma pack(push, 1)  // 设置对齐方式为 1 字节对齐
​
typedef struct {
    char a;        // 1 字节
    uint16_t b;    // 2 字节
    uint32_t c;    // 4 字节
} PackedStruct;
​
#pragma pack(pop)   // 恢复默认对齐方式
使用 Protobuf 进行序列化:

定义 .proto 文件:

syntax = "proto3";
​
message PackedData {
    int32 a = 1;
    int32 b = 2;
    int32 c = 3;
}
序列化和反序列化过程:

#include <stdio.h>
#include <string>
#include "packed_data.pb.h"  // 通过 protoc 生成的头文件
​
int main() {
    PackedStruct original = {'A', 0x1234, 0x56789ABC};
    PackedData data;
​
    // 填充数据
    data.set_a(original.a);
    data.set_b(original.b);
    data.set_c(original.c);
​
    // 序列化数据
    std::string serialized_data;
    data.SerializeToString(&serialized_data);
​
    // 反序列化数据
    PackedData deserialized_data;
    deserialized_data.ParseFromString(serialized_data);
​
    printf("a: %d, b: %d, c: %d\n", deserialized_data.a(), deserialized_data.b(), deserialized_data.c());
​
    return 0;
}

总结

  • 填充字节:在 protobuf 的序列化过程中,填充字节不会被考虑,因为 protobuf 以紧凑的二进制格式存储数据,按字段编码实际数据。

  • 传输效率:使用 protobuf 可以减少传输数据的开销,因为它使用了紧凑的编码格式,并且不会传输填充字节。

  • 网络传输:通过 protobuf 序列化的数据流是经过压缩和优化的,不会包括结构体内存对齐相关的填充字节。

因此,protobuf 能够有效地减小数据的传输压力,并且不受结构体内存对齐操作的影响。


原文地址:https://blog.csdn.net/qq_41505080/article/details/142418140

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!