Google Protocol Buffers 简称 Protobuf,它提供了一种灵活、高效、自动序列化结构数据的机制,能够联想 XML,可是比 XML 更小、更快、更简单。仅须要自定义一次你所需的数据格式,而后用户就可使用 Protobuf 编译器自动生成各类语言的源码,方便的读写用户自定义的格式化的数据。与语言无关,与平台无关,还能够在不破坏原数据格式的基础上,依据老的数据格式,更新现有的数据格式。前端
先后端都是以二进制形式进行交互信息。先后端定义proto后缀的文件,以此文件来当文档来进行沟通。java
如下为protobuf文件的demo,test.proto,文件的结构确实简单明了。node
enum FOO {
BAR = 1;
}
message Test {
required float num = 1;
required string payload = 2;
optional string payloads = 3;
}
message AnotherOne {
repeated FOO list = 1;
}
复制代码
后端以node为例子: 安装bufferhelper以及protocol-buffers进行解析protobuf文件ios
npm install bufferhelper
npm install protocol-buffers
复制代码
前端须要安装解析protobuf的环境。 mac使用brew安装protobuf环境。此操做须要先安装Homebrew环境。具体的Homebrew的安装自行搜索。 windows的前端环境安装有点不同,自行搜索。npm
brew install protobuf
复制代码
测试前端proto环境是否是安装好了,若是有版本就是安装好了。json
protoc --version
复制代码
在进行先后端交互以前,前端须要进行编译proto文件。 test.proto为前端以及后端相同的proto文件。先编译为js文件再执行。首先进入node项目的proto的目录下面,执行下面的命令以后会生成test_pb.js文件。最后js只须要解析这个文件便可。前端也须要执行这样的操做,由于我这边是先后端分离的。是两个项目,因此两个项目都须要编译。axios
protoc --js_out=import_style=commonjs,binary:. test.proto
复制代码
后端赋值proto文件的内容并传给前端。 后端传protobuf二进制给前端,要先转化为json才能够给前端。否则的话前端会转化成乱码的。前端须要请求此路由。windows
app.get('/proto/get', function (req, res) {
let protobuf = require('protocol-buffers')
let messages=protobuf(fs.readFileSync('./proto/test.proto')
let buf = messages.Test.encode({
num: 42,
payload: 'hello world node js and javahhh呵呵呵',
payloads: ''
})
console.log(buf) // 打印出来的是二进制流
res.send(JSON.stringify(buf)); //须要进行json化而后给前端。否则的话浏览器会自动解析成文字的
})
复制代码
前端须要进行接受二进制流 先引入proto.js文件以及protobufjs插件后端
import awesome from '../../proto/test_pb.js'
复制代码
前端用axios请求/proto/get的路由,在回调函数里的res.data为后端的返回值。进行如下操做。打印出来的message3也是解析好的文件。浏览器
axios({
method:'get',
url: '/proto/get',
headers: { 'contentType':'application/x-protobuf'} }).then(res => {
let message3 = awesome.Test.deserializeBinary(res.data.data)
let nums = message3.getNum()
console.log(nums) // nums=42。解析出来就是后端传过来的42
let pm = awesome.Test.deserializeBinary(res.data.data)
let protoBuf = pm.toObject()
console.log('protoBuf: ', protoBuf) // 打印出来是一个对象
}).catch((error) => {
console.log(error)
})
复制代码
前端须要进行proto文件的赋值以及转换为二进制给后端 引入须要依赖的文件。
import awesome from '../../proto/test_pb.js'
import protobuf from 'protobufjs'
复制代码
let message = new awesome.Test() // 调用Person对象 实例化
// 赋值
message.setNum(23)
message.setPayload('asd')
// 序列化
let bytes = message.serializeBinary() // 字节流
let blob = new Blob([bytes], {type: 'buffer'});
axios({
method:'post',
url: '/proto/send',
data: blob,
headers: {
'Content-Type': 'application/octet-stream' // 这里根据后台要求进行设置的,若是没有要求应该是 application/octet-stream (二进制流)
}
}).then(res => {
console.log(res)
}).catch((error) => {
console.log(error)
})
复制代码
后端须要接受文件 引入文件
let BufferHelper = require('bufferhelper');
复制代码
接收字节流的代码
app.post('/proto/send', function (req, res) {
let bufferHelper = new BufferHelper();
req.on("data", function (chunk) {
bufferHelper.concat(chunk);
});
req.on('end', function () {
let protobuf = require('protocol-buffers')
let buffer = bufferHelper.toBuffer();
console.log(buffer) // 这里已经就是二进制文件了
let message3 = awesome.Test.deserializeBinary(buffer)
console.log(message3.getNum()) // 打印的就是前端传的23
let pm = awesome.Test.deserializeBinary(buffer)
let protoBuf = pm.toObject()
console.log(protoBuf) // 打印的是{ num: 23, payload: 'asd', payloads: 'asds' }
console.log(protoBuf.num) // 打印23
});
})
复制代码
以上就是关于protobuf的先后交互。若有错误,请指出。