Javascript中Google Protobuf编解码,捎带着ByteBuffer

冬日暖阳,暖和

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容