Protobuf是Google的一种数据交换格式,编码后的信息以二进制的格式传输,被压缩过的信息,不仅信息量少,而且传输速度快、效率高。还有一个亮点,那就是跨平台(操作系统)、跨语言。
在Netty整合Protobuf编解码,并解决半包问题一文中,详细介绍了它在Java开发语言中的使用。在Java中的应用,属于服务器端的使用。在客户端Javascript中是如何使用的呢,下面介绍一下它在Javascript中的使用。
在使用之前,需要做一些准备工作。准备一份.proto文件,电脑上有protoc生成文件的压缩包,电脑上安装过vue的环境,这两个主要用于protobuf的js文件生成。没有的,现在安装一下吧。
第一步,下载生成代码的压缩包,也就是protoc,打开官网https://github.com/protocolbuffers/protobuf/releases页面,本次使用的压缩包是protoc-3.10.0-win32,用它即可生成对应的java文件,也可以生成对应的javascript文件;
image第二步,解压压缩包,来到压缩包下面,以管理员的身份打开cmd窗口,执行生成命令;
用于测试的chat.proto文件;
syntax = "proto3";//使用proto版本3
package com.example.demo.msg;//java文件所在的包
//option java_package = "com.example.demo.msg"; //设置java对应的package
//option java_multiple_files = true; //设置为true时,每个对象生成一个文件,否则所有对象都在一个java文件中
/**
* 聊天类型,枚举类型
*/
enum ChatType {
CHAT_TYPE_UNKNOW = 0;//未知
CHAT_TYPE_PUBLIC = 1;//群聊
CHAT_TYPE_PRIVATE = 2;//一对一聊天
}
/**
* 聊天信息结构体
*/
message ChatReqBody {
string uid = 1;//消息id
string time = 2;//消息发送时间
ChatType type = 3; //聊天类型
string text = 4; //聊天内容
string toId = 5; //目标用户id,
string fromId = 6; //发起用户id,用_间隔的,在js中是大小写,否则除首字母外都是小写
}
/**
* 聊天响应结构体
*/
message ChatResBody {
string uid = 1;//消息id
uint32 sendType = 2; //发送状态
}
在这里只要生成js的文件即可;
//对应的Java文件生成命令,非windows系统,把protoc.exe改成protoc即可
protoc.exe --java_out=./ chat.proto
//对应的Js文件生成命令
protoc.exe --js_out=import_style=commonjs,binary:. chat.proto
操作示例图
第三步,把生成好的js文件拷贝到项目文件夹下,接下来需要使用vue命令,生成需要的js文件;没有安装vue的,到官网 https://nodejs.org/en/download/ 下载适合自己系统的版本进行安装,这里使用的是win10 64位的系统;下载安装版的,一步一步安装即可;
image测试vue的安装是否成功,安装成功后,会打印当前vue的版本
node -v
第四步,来到js所在的文件目录下,对已经生成好的js文件再次处理;
首先创建一个js文件,命名为exports.js,exports.js文件内容如下,导出的js文件指向chat_pb.js文件;
var chatProto = require('./chat_pb');
接着,打开cmd窗口进入到chat_pb.js目录下;也可使用快捷键ctrl+shift+点击鼠标右键,打开powershell窗口,依次执行下面的命令:
//安装require命令
npm install -g require
//安装browserify命令
npm install -g browserify
//安装google-protobuf架包
npm install google-protobuf
//最后执行的命令
browserify exports.js > chat.js
命令运行结果图,如下所示:
image执行完上面的这些命令后,可以看到在chat_pb.js所在的文件目录下,生成了一个文件名为chat.js的文件,还有google-protobuf的插件包;
image第五步,接下来在页面里引入最后生成的chat.js文件,下面是html页面的代码;
<!DOCTYPE html>
<!--这个后台使用了thymeleaf模板,pom文件中记得导入thymeleaf的架包-->
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<p>Google Protobuf Javascript编解码测试</p>
<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<!--引入Google Protobuf的js文件-->
<script th:src="@{/test1/chat.js}"></script>
<script th:inline="javascript" >
var chatReqBody = new proto.com.example.demo.msg.ChatReqBody();
chatReqBody.setUid("111111");
//枚举的使用
chatReqBody.setType(proto.com.example.demo.msg.ChatType.CHAT_TYPE_PRIVATE);
chatReqBody.setFromid("1");//这里的Fromid除了首字母外都是小写的,用下划线分割时,后面的id才会变成Id
chatReqBody.setToid("2");
chatReqBody.setText("hello");
chatReqBody.setTime("2019-11-28 20:17");
//进行编码
var bytes = chatReqBody.serializeBinary();
console.log("编码后的长度:" + bytes.byteLength);
console.log("编码后:" + bytes);
//解码操作
var enChatReqBody = proto.com.example.demo.msg.ChatReqBody.deserializeBinary(bytes);
console.log("解码后:" + enChatReqBody);
</script>
</body>
</html>
运行结果如下图所示:
测试结果图
仅仅把信息编码了似乎还不够,如果还需要在该信息加上信息的长度,然后再传递到后台,解决粘包半包的问题,该怎么办呢?这里又涉及到另一个插件ByteBuffer,来看下ByteBuffer如何使用的吧。
第六步,使用vue命令安装ByteBuffer,就在上面的js文件上进行追加吧;
npm install ByteBuffer
命令运行后的结果
最后,看看ByteBuffer如何使用吧。
//ByteBuffer操作
var sbuf = new ByteBuffer();
var buffer = sbuf.int32(bytes.byteLength)//增加了长度
.byteArray(bytes, bytes.byteLength)
.pack(); //打包
console.log("ByteBuffer编码后的长度:" + buffer.byteLength);
console.log("ByteBuffer编码后:" + buffer);
//解包操作
var rbuf = new ByteBuffer(buffer);
//解包出来是一个数组,按照编码的顺序来
var arr = rbuf.int32().byteArray(null, bytes.byteLength)
.unpack();//结尾调用解包方法
console.log(arr);
enChatReqBody = proto.com.example.demo.msg.ChatReqBody.deserializeBinary(arr[1]);
console.log("ByteBuffer后再解码:" + enChatReqBody);
运行结果图
参考资料:
https://my.oschina.net/zyw205/blog/1827719?nocache=1528879797491
https://github.com/play175/ByteBuffer
网友评论