通信协议设计
基本要素消息帧完整性的判断方法主流序列化协议 Protobuf
使用protobuf
IDL语法
编译.proto命名规范 在C++中使用protobufprotobuf 编码
通信协议设计 基本要素要能完整地识别一帧数据(帧完整性)能够进行序列化和反序列化能够进行协议升级(包括客户端和服务端,需要指明协议版本)协议具备安全性(加解密)能够实现数据压缩,减小传输数据量 消息帧完整性的判断方法
1、强制固定每个消息的数据长度,比如规定每个消息都发128字节
这显然是很拙劣的方法。以特定符号来作为分界,如“rn”
2、如果传输的消息中也带有这个符号就不可行了。3、固定消息头head+消息体结构body
消息头的长度固定,其中带有指明消息数据长度的字段。先接收头部,解出这个消息完整⻓度,再按此⻓度接收消息体。
4、字符流的头部+消息体,如HTTP协议和redis协议是⽬前各种⽹络应⽤⽤的最多的⼀种消息格式
头部中有个字段存储消息总⻓度(content-length),根据特殊字符(⽐如rn或者 )判断头部的完整性。由于不确定头部的长度,显然比第3种方法要麻烦一些。很多时候我们觉得HTTP协议简单只是因为我们对它比较熟悉罢了。
哪些场景适合使用HTTP协议:
对公⽹⽤户api,HTTP协议的穿透性最好,所以最适合;效率要求没那么⾼的场景;希望提供更多⼈熟悉的接⼝,⽐如新浪微博、腾讯提供的开放服务接⼝;
Protobuf就是基于方法3的。
主流序列化协议| 类型 | 通信性 | 数据量 | 格式 |
|---|---|---|---|
| XML | 通用 | 重量级 | 文本(清晰易懂) |
| JSON | 通用 | 轻量级 | 文本(方便调试) |
| Protobuf | 独立 | 轻量级 | 二进制(高效) |
序列化和反序列化性能对比:
10万次序列化
10万次反序列化
Protobuf
Protocol buffers 是⼀种语⾔中⽴、平台⽆关、可扩展的序列化数据的格式,只需使⽤ IDL(Interface description language,接⼝描述语⾔)对数据结构进⾏描述,就可以利⽤ Protocol buffers 的代码⽣成⼯具⽣成与序列化和反序列化相关的底层代码。
我们可以简单理解为:Protobuf根据 .proto 文件将一个类序列化为一个二进制串,然后通过API进行传输或存储。
使用protobuf- 根据消息的结构编写.proto文件;⽣成对应的.pb.cc和.pb.h⽂件。其中定义了消息的类,消息字段就是类成员,包含了设置和获取各个成员的方法;在代码中使用这些类并编译:
g++ -std=c++11 -o proto_test *.cc *.pb.cc -lprotobuf -lpthread
使用 libprotobuf 提供的API可以对消息类进行序列化和反序列化,如果消息的接收端没有描述该消息结构的 .proto 文件,拿到数据以后也无法解释成正常的数据。因此也可以认为 Protocol Buffer 比 JSON,XML 更安全一点点。
IDL语法如何编写 .proto 文件请参考Language Guide (proto3)。
编译.proto生成.pb.cc和.pb.h 文件的指令为:
protoc -I=input_dir --cpp_out=output_dir *.proto命名规范
message、枚举类型、服务名、方法名等均采用驼峰命名法,开头首字母大写命名。字段名采用下划线分隔法命名。
service ItemService {
rpc GetSomething(ItemRequest) returns (ItemResponse);
}
message ItemServerRequest {
required string item_name = 1;
enum ItemType {
TYPE1_VALUE = 0;
TYPE2_VALUE = 1;
}
}
在C++中使用protobuf
参考Protocol Buffer Basics: C++。
protobuf 编码编码有助于对通过对序列化后的数据进行压缩。参考高效的数据压缩编码方式 Protobuf。


![大学C/C++语言程序设计基础(第3版)([C/C++后端开发学习]22 协议设计与Protobuf) 大学C/C++语言程序设计基础(第3版)([C/C++后端开发学习]22 协议设计与Protobuf)](http://www.mshxw.com/aiimages/31/776502.png)
