zoukankan      html  css  js  c++  java
  • websoket使用Protocol Buffers3.0传输

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

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

    定义一个.proto

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

    加载:

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

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

    根据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);

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

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

    解析:

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

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

    这个时候需要将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的兼容性如下:

    比如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的方式。

  • 相关阅读:
    vim 查找文件指定内容所在位置
    tar 使用小技巧
    dpkg 安装deb包
    Jetbrains 全家桶(IDEA,PyCharm...)
    Python如何生成requirements.txt文件
    MySQL——导入数据报字段编码错误
    视图的概念、作用以及如何创建
    hive与hbase及MySQL的区别
    mysql—排序函数rank() over()、dense_rank() over()、row_num() over()
    mysql —net start mysql 命令发生系统错误5和错误1058的解决方法
  • 原文地址:https://www.cnblogs.com/stoneniqiu/p/6769561.html
Copyright © 2011-2022 走看看