简单解释下protobuf ,它就是个又小又快的数据传输格式。
从网上下载了一个原生js+webscoket+protobuf的demo
找的这个demo是可以完美运行(注意要在服务器上打开,本地双击是没用的,demo只上传了前端部分
遇到坑了
当你准备将这个原生js的demo修改成vue项目时,你就会遇到第一个坑了,引入后台给的 xxxx.proto文件的时候会报 illegal token '<' (/xxxx.proto, line 1) ,第一行缺少‘<’这玩意,但源码里没有这个,网上查也有老哥遇到这种情况。所以直接修改时行不通的。
重头来过 从安装protobuf编译器开始吧
vue中使用protobuf踩坑记 这位老哥的文章讲的很详细,我就是参照文章里的步骤走下来的,读者移步去将文章看完再回来看下面的吧
webscoket配置的代码
<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;
}
后台给的文件编译生成proto.js代码参考
/*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;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。