通信协议的设计核心有两点
1.解析效率
2.可扩展升级
协议的设计细节包括
1.帧数据完整性判断
2.序列化与反序列化
3.协议升级
4.协议安全
5.数据压缩
网络通信协议的设计目标为:
1.解析效率:互联网业务具有高并发的特点,解析效率决定了使用协议版本的CPU成本
2.编码长度:信息编码出来的长度,编码长度决定了使用该协议的网络宽带以及存储成本
3.可读性:编码后的数据的可读性决定了使用协议的调试和维护版本(不同的序列化协议是不同的应用场景)
4.兼容性:互联网的需求具有灵活多变的特点,协议会经常升级,使用协议的双方可以独立升级协议,增减协议中的字段是非常重要的
5.跨平台语言:互联网的业务设计不同的平台和语言,必须C/C++,JAVA,JS,Object-c等
6.安全可靠:防止数据被破解
协议概述:
协议是一种约定,通过约定,不同的进程可以对同一段数据产生相同的理解,从而可以相互协作,存在进程间通信的程序就一定需要协议
包完整性判断
为了能让对端知道如何给包分界,目前一般有以下做法
1.以特定的符号分界,如每个包都以特定的字符结尾(如\r\n),当在字节流中读到该字符时,则表明上一个包到此为止;
2.固定包头+包结构体,这种结构中一般包头部分是一个固定字节长度的结构,并且包头中会有一个特定的字段指定包体的大小。收包时,先接收固定的字节数的头部,解析出包整体长度,再解析出整个包。这是目前网络中应用最多的一种包格式;header+body
3.在序列化的后的buffer前面增加一个字符流的头部,其中有字段存储包总长度,根据特殊字符(比如\n或\0)判断头部的完整性。这通常比上述结构蛮烦很多HTTP和redis采用的是这种方式。收包时先判断已收到数据中是否包含结束符,收到结束符的时候解析包头,解出这个包完整长度,按此包接收包体
protobuf的使用
protobuf 是一种语言中立,平台无关,可扩展的序列化数据的格式,可用于通信协议,数据存储等。
Protobuf buffers在序列化数据方面,它是灵活的,高效的。相对于XML来说,Protobuf buffers更加小巧,更加快速,更加简单。一旦定义了要处理的数据结构之后,就可以利用protobuf buffers 的代码生成工具生成相关的代码。甚至可以在无需重新部署的情况下更新数据结构。只需要Protobuf对数据结构进行一次描述,即可利用各种不同语言或从不同数据流中对你的结构化数据轻松读写。
Protobuf buffers 很适合做数据存储或RPC数据交换格式。可用于通讯协议,数据存储等领域的语言无关,平台无关,可扩展的序列化结构数据格式。
Protobuf 协议的工作流程
IDL 是 Interface description language的缩写,指接口描述语言
可以看到,对于序列化协议来说,使用方只需要关注业务对象本身,即idl定义(.proto),序列化和反序列化的代码只需要通过工具生成即可
protobuf 编译安装
1.源码下载
https://github.com/protocolbuffers/protobuf
2.解压
tar -zxvf protobuf-cpp-3.8.0.tar.gz
3.编译
cd protobuf-3.8.0
./configure
make
make install
4.显示版本信息
protoc --version
将proto文件生成相对于的.cc和.h文件
proto -l = /路径1 --cpp_out=./路径2 /路径1/addressbook.proto
路径1为.proto所在路径
路径2为.cc和.h生成的路径
将指定protoc文件生成.pb.cc和.pb.h
protoc -l=./ --cpp_out=./*.proto
编译范例:
proto标量数值类型
protobuf编码原理
varints编码
通常来说,普通的int数据类型,无论其值的大小,所在用的存储空间都是相等的,这点可以引起人们的思考,是否可以根据数值的大小来动态地占用存储空间,使得值比较小的数值占用较少的字节数,值较大的数值占用较多的字节数,这便是变长整型编码的基本思想,采用变长整型编码的数字,其占用的字节数不是完全一致的,为了达到这一点,Varints编码使用每个字节的最高有效位作为标志位,而剩余的七位以二进制的补码的形式来存储数字本身当最⾼有效位为 1 时, 代表其后还跟有字节, 当最⾼有效位为 0 时, 代表已经是该数字的最后的⼀个字节, 在 Protobuf 中, 使⽤的是Base128 Varints 编码, 之所以叫这个名字原因即是在这种⽅式中, 使⽤ 7 bit 来存储数字, 在Protobuf 中, Base128 Varints 采⽤的是⼩端序, 即数字的低位存放在⾼地址, 举例来看, 对于数字1, 我们假设 int 类型占 4 个字节, 以标准的整型存储, 其⼆进制表示应为