如何设计一个通信协议

1. 网络层次

1.1具体层次以及封装

Snipaste_2024-10-22_15-30-30

  • 封装的协议结构一般是协议头+数据。

2. 网络通信存在问题

2.1 设计协议时,边界问题如何处理

场景以及问题:在TCP流式传输中,流式传输也就是一端只关心向管道发送数据,另外一边只要管道存在数据就接收数据。一个客户端发送N个100字节的消息,此时服务器接收数据可以每次读取100字节。但是当客服端每次发送的数据长度不一样的时候,比如发送200字节、500字节,此时如何对接收的数据进行一个拆分。

解决:

根据标识去拆分数据得到完整的一个消息。关键在于一个消息的起始边界的判定。

2.2 发送方和接收方如何通信

将客服端封装成应该person对象,然后发送对象以及对象的大小,也就是send(&person,sizeof(person))?存在什么问题?

问题就是如果数据是在堆上时,使用sizeof是有问题的。因为sizeof不能计算动态分配的内存。一般网络传输中都是使用序列化(将数据对象转换为二进制过程)和反序列化(将二进制恢复为数据对象过程)进行通信的。

3. 一个完整的通信协议应该包括以下组成部分:

1协议字段补充

  1. 如果需要处理不同业务功能时,可以在body里面封装不同的cmd(command),每一个不同的cmd标识不同的业务功能,比如login表示登录,regist表示注册。
  2. appid:对外提供SDK服务时,用来识别不同的客服,比如英雄联盟的客户以及绝地求生的客户。
  3. server_id:对应命令的分组。比如文件命令和网络命令,文件file命令下可以存在很多子命令,比如ls,tree等等。网路命令下也可以存在很多子命令,比如lsof,top等等。
  4. command_id:具体的子命令,比如ls、tree等。

4. protobuf的使用

4.1 准备工作
  1. 下载安装protobuf工具,编译安装protobuf的cpp版本。
  2. 编写proto文件:也就是一个数据结构。包含通信协议的一些命令之类的详细结构。客服端和服务器需要同一份proto文件。主要这里不是说客服端和服务端在各自的git仓库建立一个proto文件,而是从一个git仓库拉取同一份proto文件(主要是为了后期维护,当一份修改时,另外一方可以实时知道)。
  3. 将proto文件生成对应的.cc和.h文件
4.2 protobuf经验总结
  1. proto文件命名规则:比如IMLogin.pro,IM表示即时通信项目,Login登录相关的proto文件
  2. proto命名空间:需要和文件命令空间对应。
  3. 引用文件:引用其他proto文件,需要加上命名空间package。(PDU:protocol data unit:通信数据单元。)
  4. 协议封装。
posted @ 2024-10-22 17:05  炫炫子  阅读(31)  评论(0编辑  收藏  举报