讲师中心 微信公众号
AI工具推荐 视频效率加速

c++如何将对象转换为Byte流进行网络传输_序列化方案【深度】

秋杰同学_4044

秋杰同学_4044

发布时间:2026-04-08 20:10:03

|

822人浏览过

|

来源于php中文网

原创

不能直接 memcpy 对象到网络缓冲区,因为C++对象含虚表指针、指针成员、非POD类型等,导致跨平台解析失败;即使POD也需处理字节序、对齐和大小端差异。

c++如何将对象转换为byte流进行网络传输_序列化方案【深度】

为什么不能直接 memcpy 对象到网络缓冲区

因为 C++ 对象内存布局不等于可传输的字节序列。虚函数表指针、内存对齐填充、指针成员(如 std::string 内部指向堆内存)、非 POD 类型(如含构造/析构函数的类)都会导致 memcpy 出错或跨平台不可用。即使对象是 POD,不同编译器或 ABI 下的结构体对齐(#pragma pack 缺失)、大小端差异也会让接收端解析失败。

常见错误现象:recv 后 reinterpret_cast<mystruct>(buf)</mystruct> 访问崩溃;同一结构体在 x86_64 和 ARM64 上 sizeof 不同;std::vector 成员变成野指针。

  • 所有含指针、动态内存管理、虚函数、非平凡构造/析构的类型,必须显式序列化
  • POD 结构体也需手动处理字节序(htons/htonl),不能裸传
  • 跨语言通信时,C++ 的 enum class 默认底层类型不确定,需显式指定(如 enum class Status : uint8_t)

用 protobuf 快速实现零拷贝兼容序列化

Protobuf 是最稳妥的生产级方案:协议定义与语言解耦、自动生成 C++ 代码、支持 optional/oneof/嵌套、内置字节序和对齐处理、有成熟流式读写接口。

使用场景:微服务间通信、客户端-服务器状态同步、需要向前/向后兼容的长期协议。

立即学习“C++免费学习笔记(深入)”;

实操步骤:

  • 写 .proto 文件,用 syntax = "proto3";,字段全部加 optional(避免默认值歧义)
  • 用 protoc --cpp_out=. mymsg.proto 生成 mymsg.pb.h 和 mymsg.pb.cc
  • 序列化:调用 msg.SerializeAsString() → 返回 std::string,其 .data() 和 .size() 可直接传给 send()
  • 反序列化:先 recv 到 std::string buf,再 msg.ParseFromArray(buf.data(), buf.size())

注意:SerializeAsString() 每次分配新内存,高吞吐场景可用 SerializeToCodedStream() 配合预分配 google::protobuf::io::ArrayOutputStream 实现零拷贝写入。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

手写二进制序列化时必须检查的 4 个细节

若因性能或协议约束必须手写(如高频游戏帧同步),以下检查点漏掉一个就可能线上出问题:

  • static_assert(std::is_standard_layout_v<t> && std::is_trivially_copyable_v<t>, "")</t></t> —— 确保结构体可安全 memcpy,否则必须逐字段序列化
  • 每个整数字段写入前调用 htons/htonl,读取后调用 ntohs/ntohl;uint64_t 用 htonll(需自己实现或用 bswap_64)
  • std::string 必须先写长度(uint32_t,网络序),再写字符数据;空字符串也要写长度 0
  • 结构体末尾不要有未初始化 padding,用 static_assert(sizeof(T) == expected_size, "") 校验,并在类定义开头加 #pragma pack(push, 1),结尾加 #pragma pack(pop)

示例关键片段:

#pragma pack(push, 1)
struct PlayerState {
    uint32_t id;
    float x, y;
    uint8_t status;
};
#pragma pack(pop)
static_assert(sizeof(PlayerState) == 13, "PlayerState layout broken");

std::span + std::byte 无法替代序列化协议

有人试图用 std::span<const std::byte></const> 包装对象地址来“泛化”发送,这是危险的抽象。它只是把 memcpy 封装得更隐蔽,没解决任何根本问题。

原因:

  • std::span 不改变底层对象的内存语义 —— 虚表、指针、对齐问题全在
  • 接收端仍需知道 exact type 和 exact layout,无法做字段校验、版本迁移、缺失字段默认值填充
  • 调试困难:gdb 看到一串 std::byte 完全无法识别业务含义

真正需要的是协议描述能力(IDL),不是类型擦除。哪怕只用 JSON,也比裸 std::span 更可靠 —— 至少能 human-readable、字段名明确、容错性高。

复杂点在于:序列化从来不只是“把内存发出去”,而是“定义双方如何一致理解字节”。这个契约一旦定下,后续增删字段、类型变更、多语言互通,全靠协议层兜底。手写二进制看似快,但协议演进成本远高于初期多花半小时配好 protobuf。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2195

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3482

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1176

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

4019

2025.09.10

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6819

2023.08.02

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1818

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2884

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6204

2023.10.24

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn