简单解释下protobuf ,它就是个又小又快的数据传输格式。
找的这个demo是能够完美运行(注意要在服务器上打开,本地双击是没用的,demo只上传了前端部分
遇到坑了javascript
当你准备将这个原生js的demo修改为vue项目时,你就会遇到第一个坑了,引入后台给的 xxxx.proto文件的时候会报 illegal token '<' (/xxxx.proto, line 1) ,第一行缺乏‘<’这玩意,但源码里没有这个,网上查也有老哥遇到这种状况。因此直接修改时行不通的。
vue中使用protobuf踩坑记 这位老哥的文章讲的很详细,我就是参照文章里的步骤走下来的,读者移步去将文章看完再回来看下面的吧
<template> <div class="hello"> <h1>欢迎访问客服系统</h1> <form onsubmit="return false"> <textarea name="message" style="width: 400px;height: 200px" v-model="textarea"></textarea> <input type="button" value="发送数据" @click="send();"> <h3>回复消息:</h3> <textarea id="responseText" style="width: 400px;height: 300px;"></textarea> <input type="button" onclick="javascript:document.getElementById('responseText').value=''" value="清空数据"> </form> </div> </template> <script> import protoRoot from '@/proto/proto.js'//我这里生成的文件名为proto import protobuf from "protobufjs" export default { name: 'HelloWorld', data () { return { socket:null, webSocketConfig:{ url:'192.168.1.9:8899' }, textarea:'' } }, mounted(){ this.webscoket() }, methods:{ // 初始化webscoket webscoket(){ const _this = this; if ('WebSocket' in window) { if (_this.socket == null) _this.socket = new WebSocket("ws:" + _this.webSocketConfig.url + "/ws"); else _this.socket.onopen(); } else if ('MozWebSocket' in window) { _this.socket = new MozWebSocket("ws:" + _this.webSocketConfig.url + "/ws"); } else { _this.socket = new SockJS(_this.webSocketConfig.projectName + "sockjs/ws"); } //客户端收到服务器消息的时候就会执行这个回调方法 _this.socket.onmessage = function (event) { // 解码 _this.responseUserDecoder({ data:event.data, success: function (responseData) { var ta = document.getElementById("responseText"); var content = "客服小姐姐: " + responseData.userName + ", 小姐姐年龄: " + responseData.age + ", 密码: " + responseData.password; ta.value = ta.value + "\n" + content; } }) } //链接创建的回调函数 _this.socket.onopen = function (event) { var ta = document.getElementById("responseText"); ta.value = "链接开启"; } //链接报错的回调函数 _this.socket.onerror = function (evnt) { console.log("error..."); console.log(evnt); }; //链接断掉的回调函数 _this.socket.onclose = function (event) { var ta = document.getElementById("responseText"); ta.value = ta.value + "\n" + "链接关闭"; } }, //发送数据 send(){ let _this=this if (!window.WebSocket) { return; } // socket.binaryType = "arraybuffer"; // 判断是否开启 if (_this.socket.readyState !== WebSocket.OPEN) { alert("链接没有开启"); return; } var data = { userName: _this.textarea, age: 18, password: "11111" }; _this.requestUserEncoder({ data:data, success:function(buffer){ _this.socket.send(buffer); } }); }, /** * 发送的消息编码成 protobuf */ requestUserEncoder(obj){ var data = obj.data; var success = obj.success; // 成功的回调 const RequestUser = protoRoot.lookup('com.example.nettydemo.protobuf.RequestUser') var buffer=RequestUser.encode(data).finish() if (typeof success === "function") { success(buffer) } }, /** * 接收到服务器二进制流的消息进行解码 */ responseUserDecoder(obj){ var data = obj.data; var success = obj.success; // 成功的回调 const ResponseUser = protoRoot.lookup('com.example.nettydemo.protobuf.ResponseUser') var reader = new FileReader(); reader.readAsArrayBuffer(data); reader.onload = function (e) { var buf = new Uint8Array(reader.result); var responseData = ResponseUser.decode(buf); if (typeof success === "function") { success(responseData) } } } } } </script>
syntax ="proto2"; package com.example.nettydemo.protobuf; //optimize_for 加快解析的速度 option optimize_for = SPEED; option java_package = "com.example.nettydemo.protobuf"; option java_outer_classname="MessageData"; // 客户端发送过来的消息实体 message RequestUser{ optional string user_name = 1; optional int32 age = 2; optional string password = 3; } // 返回给客户端的消息实体 message ResponseUser{ optional string user_name = 1; optional int32 age = 2; optional string password = 3; }
/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ "use strict"; var $protobuf = require("protobufjs/light"); var $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $protobuf.Root())) .addJSON({ com: { nested: { example: { nested: { nettydemo: { nested: { protobuf: { options: { optimize_for: "SPEED", java_package: "com.example.nettydemo.protobuf", java_outer_classname: "MessageData" }, nested: { RequestUser: { fields: { userName: { type: "string", id: 1 }, age: { type: "int32", id: 2 }, password: { type: "string", id: 3 } } }, ResponseUser: { fields: { userName: { type: "string", id: 1 }, age: { type: "int32", id: 2 }, password: { type: "string", id: 3 } } } } } } } } } } } }); module.exports = $root;