簡單解釋下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;