首页 技术 正文
技术 2022年11月6日
0 收藏 824 点赞 962 浏览 2400 个字

Protocol Buffers是Google推出的一个数据交换格式,相对于xml它的体积更小,更快,因为它是二进制传输的。3.0相对于2.0变动比较大。这些变动可以去看官方说明。

在前端使用ProtoBuf.js解析.proto文件,先需要再界面上引入protobuf.js。

定义一个.proto

syntax = "proto3";
// Token
message MyModel{
string UserID = ;
string Device = ;
}
message Message{
string ChannelID = ;
bytes Content = ;
}

加载:

protobuf.load("Models.proto", function (err, root) {
if (err)
throw err;
console.log(root);
var MyModel = root.lookupType("MyModel");
console.log(MyModel);
});

websoket使用Protocol Buffers3.0传输

Root包含了我们定义的两个模型。拿到这个模型就可以用来发送消息和解析消息了。注意到我们的上面的Message的Content是bytes类型。JavaScript本身是没有这个类型的。

websoket使用Protocol Buffers3.0传输

根据protobuf.js的官方说明可以通过base64编码来实现:

function base64Encode(input) {
var rv;
rv = encodeURIComponent(input);
rv = unescape(rv);
rv = window.btoa(rv);
return rv;
}
 var buffer1 = base64Encode("消息");
console.log(buffer1);
var model = { ChannelID: "12121", Content: buffer1 };
var message = Message.create(model);//创建模型
var buffer = Message.encode(message).finish();//转成二进制
console.log(buffer);

运行页面,对象已经被转化了数组

websoket使用Protocol Buffers3.0传输

这个时候可以用的WebSocket的send方法将对象发送到后端,但还可以根据和后端约定的协议对消息再做一次转换。

解析:

  var decodeModel = Message.decode(buffer);
console.log(decodeModel);
console.log(Ut8ArrayToStr(decodeModel.Content));

拿到buffer之后再次转化成我们的对象

websoket使用Protocol Buffers3.0传输

这个时候需要将Uint8Array转成字符串,才能直观的获得我们的Content中的内容。

function Ut8ArrayToStr(array) {
var out, i, len, c;
var char2, char3; out = "";
len = array.length;
i = 0;
while (i < len) {
c = array[i++];
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}

这样就完成整个过程。

小结:

实际开发中比上面介绍的要复杂,首先加载.proto对象是异步的,也就是说,在你使用WebSocket收发送消息的时候要确保已经获得了模型,也就是例子中的Message对象。另外一个是兼容性处理。protobuf.js的兼容性如下:

websoket使用Protocol Buffers3.0传输

比如ie8不支持,当然我们也不是要在IE8中使用protobuf.js,因为ie8也不支持WebSocket,我们可以用轮询。是为了避免引入protobuf.js就会报错,毕竟这个js有很多新浏览器对象。可以用typeof来阻止它在不支持的浏览器中运行。

//不支持WebSocket的 就不用初始化了
if (!window.WebSocket) return;
if (typeof exports=="undefined") return ;
exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);

同理,自己的js中也要判断。

    function loadProto() {
if (typeof protobuf == "undefined") return;//说明浏览器加载失败
protobuf.load("../xx.proto", function (err, root) {

这样如果你有备用的轮询通信方式,在ie8中也能运行起来了。

另外,Google官方也提供了JavaScript解析.proto文件的方式。

1. CommonJS-style imports (eg. `var protos = require('my-protos');`)
2. Closure-style imports (eg. `goog.require('my.package.MyProto');`)

closure-style的需要依赖goog,一大堆,而commonjs的示例更像是在node端的,在这个地方绕了一天,没成功,最后选择了protobuf.js的方式。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,030
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,520
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,368
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,147
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,781
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,859