前言
之前做游戏开发时,游戏服务端与前端采用Protobuf来进行数据传输,为了避免被人恶意破解,还对Protobuf产生的数据做了简单的偏移处理。最近又要用到Protobuf了,所以简单记录一下相关内容。
背景知识
我们日常使用最多的数据通信格式应该是JSON,但在一些请求很大的应用上,JSON有2个问题:
1.JSON中有很多业务无关数据,如大括号、中括号等,传输时,这些数据浪费带宽。
2.JSON解码速度慢,量大时,解码对服务器资源占用大了一些。
Google遇到了这些问题,然后提出了Protobuf,其核心目的就是解决上述2个问题。
Protobuf选择二进制编码的形式,将业务数据编码到其中,不会有无关数据,甚至连字段名都不会编码进去,这让带宽压力减小,此外Google自己设计了编码与解码算法,以保证资源占用合理且尽量快速的特点。
此外,Protobuf还有一个福作用:人类对编码后的数据比较难读。这个副作用从一定程度实现数据保护的效果,一些网站利用这个特性实现了反爬。
因为发展原因,Protobuf分为proto2和proto3两个版本,两者是不相兼容的,即使用proto2应用无法与使用proto3的应用通信,本文主要讨论proto3,且不会涉及proto2与proto3的比较。
proto文件语法
使用Protobuf通信的第一步,便是定义出proto文件,我们先展示一个简单的proto文件,如下:
message Person{
required string name = 1;
message Info{
required int32 id = 1;
repeated string phonenumber = 2;
}
repeated Info info = 2;
}
先思考一下,为啥需要proto文件?为何不能像JSON那样直接使用呢?
回顾一下Protobuf其中一个优点:只编码业务相关的数据到待传输的二进制流中,以节省带宽。
Protobuf实现这个特点的原理是:通信双方手里都拿着定义好的proto文件。
发送方通过这个proto文件定义发送的内容,这些内容不会需要像JSON那样,有字段名、有括号这些,接收方收到数据后,再利用手里的proto文件,按算法直接解析里面的数据。
我一直强调,JSON传输时,会有字段名、有括号,可能有人会比较懵逼,还是举个例子,如下JSON:
{"name": "ayuliao", "age": 30}
这段JSON在传输时,name和age这两个字段名也会被传输,但这两个字段名没啥业务意义,主要就是用来获取数据的,假设这段数据使用Protobuf传输,Protobuf就