自己实现自定义协议的思考

需求

  • 有三个字段,sender_uid(发送者ID)、content(消息内容)、timestamp(时间戳)
  • 低延迟、高并发、消息可靠、支持多种消息类型
  • 思考一个协议应该完成哪些步骤

思路

一个好的自定义协议设计,需要考虑消息边界、可扩展性、编解码效率和安全性。以下是一个分层的设计思路:

  1. 协议分层结构

    一个完整的网络包结构建议分为两层:包头​ 和 包体。

    • 包头 (Header):用于描述包本身,与具体业务(聊天)无关。是固定长度的二进制数据,便于快速解析。

    • 包体 (Body):承载具体的业务数据(如聊天消息)。其内容由包头中的"消息类型"决定。

B. 包体 (Packet Body)

包体是变长的,其格式由Command ID决定。对于聊天消息(假设Command ID=0x0001,私聊),其结构就是我们需要设计的"聊天消息体"。

聊天消息体设计(序列化方案对比)

您需要将{sender_uid, content, timestamp}这三个字段(以及可能的其他字段,如target_uid)序列化成二进制。

使用高效序列化库

使用Protobuf、MessagePack (MsgPack)​ 或 FlatBuffers​ 来定义消息体。

例如,用Protobuf定义 .proto文件:

protobuf 复制代码
message ChatMessage {
  uint64 sender_uid = 1;
  string content = 2;
  int64 timestamp = 3;
}
  • 优点:在性能、体积和开发效率上取得最佳平衡。自动生成编解码代码,支持向后/向前兼容(通过字段编号),是工业级标准。

  • 缺点:需要引入第三方库。

完整数据流示例(以Protobuf方案为例)

  1. 客户端构建一个 ChatMessage对象,用Protobuf库将其序列化成二进制数据 B_body。
  2. 计算 B_body的长度 len_body。
  3. 按定义填充包头,将 len_body写入"包体长度"字段。
  4. 将包头的二进制数据和 B_body拼接,得到完整的网络包 B_packet。
  5. 通过Socket(可能是基于WebSocket或Raw TCP)发送 B_packet。
  6. 服务端收到数据后:
    • 先读取固定长度的包头(例如14字节)。

    • 从包头中解析出 len_body。

    • 继续从Socket读取 len_body字节,得到完整的包体数据。

    • 根据包头的 Command ID,知道这是一个聊天消息,调用对应的Protobuf解析函数,将包体数据反序列化成 ChatMessage对象。

    • 进行业务逻辑处理(如敏感词过滤、存储、转发给目标玩家)。

相关推荐
怕浪猫5 小时前
外包和大厂的前端代码,差在凌晨三点
前端·面试·github
十年Java程序媛12 小时前
Java this 与 super 详解|继承高频踩坑 + 面试题整理
java·spring boot·面试
萧瑟余晖12 小时前
Spring Cloud配置中心与动态刷新详解
spring cloud·面试
白露与泡影13 小时前
一线 Java 后端面试八股(2026 更新版,含完整答案)
java·开发语言·面试
学到老活到老18 小时前
集合换成线程安全的,就不用加锁了吗?
java·面试
萧瑟余晖19 小时前
Spring Cloud Alibaba生态整合详解
spring·spring cloud·面试
Sailing21 小时前
【封闭结束2】Agent 意图识别:从语义理解到稳定路由
人工智能·面试·agent
Sailing21 小时前
【封闭结束1】端到端交付:Agent 一次请求如何走完全链路
人工智能·面试·agent
怕浪猫1 天前
红利窗口开着,程序员别在场边囤课
面试·github·ai编程
lll23526917791 天前
HR如何快速整理面试沟通内容?
面试·职场和发展