vue3项目使用WebSocket 传输 Protobuf 格式的数据
vue3项目中protobuf格式数据传输的示例项目。
·
前言
前端和后端数据传输常用数据格式:
JSON(JavaScript Object Notation):与 HTTP 协议和 REST API 配合使用时,JSON 数据是最常用的数据格式之一。对于 WebSocket,JSON 数据同样适用。客户端可以将消息转换为 JSON 对象,并将其发送到服务器进行处理,在服务器上生成响应并返回给客户端。
Binary Data:WebSocket 还支持二进制数据传输。此方法特别适用于需要在网络上传输大量数据的应用程序。使用二进制数据格式,您可以将数据压缩为更小的包,以提高传输速度并降低带宽消耗。
Protocol Buffers:Protocol Buffers 是一种 Google 开发的高效数据结构序列化格式。与 JSON 和 XML 不同,Protocol Buffers 将数据编码为二进制格式,可快速解析和传输。此方法特别适用于需要在网络上传输大量数据的应用程序。
但是在日常开发当中使用的最多的还是JSON格式
下面我简单介绍一下前后端使用protobuf传输数据的案例
一、基础库安装
pnpm add ws
pnpm add protobufjs
pnpm add protobufjs-cli -D
二、具体代码实现
1.服务端编写
message.proto文件定义
syntax = "proto3";
message Message {
string text = 1;
}
代码如下(示例):
const WebSocket = require('ws');
const protobuf = require('protobufjs');
const path = require('path');
// 加载 .proto 文件
const root = new protobuf.Root();
root.loadSync(path.join(__dirname, './message.proto'));
// 获取 Message 类型
const Message = root.lookupType('Message');
// 创建 WebSocket 服务器
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (socket: any) => {
console.log('Client connected');
// 接收客户端发送的消息
socket.on('message', (data: Buffer) => {
const message = Message.decode(new Uint8Array(data));
console.log('Received message:', message);
// 发送响应消息
// const response = { text: 'Hello, client!'};
// const buffer = Message.encode(Message.fromObject(response)).finish();
// socket.send(buffer);
const response = Message.create({ text: `服务端已收到数据: ${message.text}` });
// 序列化消息对象,并将其发送给服务器
const buffer = Message.encode(response).finish();
socket.send(buffer);
});
// 监听连接断开事件
socket.on('close', () => {
console.log('Client disconnected');
});
});
const http = require('http');
const fs = require('fs');
// 创建 HTTP 服务器,监听客户端请求
const httpserver = http.createServer(async (req:any , res: any) => {
console.log(`Receive request: ${req.method} ${req.url}`);
try {
// 如果请求的是 .proto 文件,则读取文件内容并返回给客户端
if (req.url.endsWith('.proto')) {
const content = await fs.promises.readFile(`${path.join(__dirname, './message.proto')}`, 'utf8');
res.setHeader('content-type', 'text/plain');
res.end(content);
return;
}
// 如果请求的不是 .proto 文件,则返回 404 Not Found 错误
res.statusCode = 404;
res.end();
} catch (err) {
console.error(err);
res.statusCode = 500;
res.end();
}
});
// 启动 HTTP 服务器
httpserver.listen(3001, () => {
console.log('HTTP server started!');
});
2.客户端代码实现
方法1
代码如下(示例):
<template>
<div style="width: 100%; height: 200px; background: darkgrey">
<div>{{ messageRef }}</div>
<button @click="sendMsg"> 发送 </button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import protobuf from 'protobufjs';
// 定义要加载的 .proto 文件 URL
const protoUrl = '/path/to/your/message.proto';
// 定义响应消息的状态
const messageRef = ref('');
const response = await fetch(protoUrl);
const content = await response.text();
// 解析 .proto 文件中的消息结构
const root = await protobuf.parse(content).root;
const MyMessage = root.lookupType('Message');
// 创建 WebSocket 连接
const ws = new WebSocket('ws://localhost:8080/');
// 监听 WebSocket 连接成功事件
ws.addEventListener('open', () => {
console.log('WebSocket connected!');
// 序列化消息对象,并将其发送给服务器
const response = MyMessage.create({ text: '客户端1连接了' });
// 序列化消息对象,并将其发送给服务器
const buffer = MyMessage.encode(response).finish();
ws.send(buffer);
});
// 监听 WebSocket 收到服务器发送过来的消息事件
ws.addEventListener('message', async (event) => {
// 解析二进制数据为 Protobuf 消息
const blob: Blob = event.data;
// Uint8Array 接收的是arrayBuffer对象这里一定要注意如果是Blob格式的数据一定要先转为arrayBuffer
const buffer = await blob.arrayBuffer();
const data = new Uint8Array(buffer);
const message = MyMessage.decode(data);
console.log(`Receive message from server: ${JSON.stringify(message)}`);
// 更新视图显示收到的消息内容
messageRef.value = message.text;
});
// 监听 WebSocket 出错事件
ws.addEventListener('error', (event) => {
console.error(event);
});
// 监听 WebSocket 关闭事件
ws.addEventListener('close', (event) => {
console.warn(event);
});
const sendMsg = () => {
const message = MyMessage.create({ text: '我是客户端1' });
// 序列化消息对象,并将其发送给服务器
const buffer = MyMessage.encode(message).finish();
ws.send(buffer);
};
</script>
方法2
方法2不同之处在与使用protobufjs-cli
工具将message.proto
文件编译出js文件 还能编译出ts声明文件,具有类型提示对TS项目更加友好
编译方法
pbjs -t static-module -w es6 -o ../web/src/components/compiled.js message.proto
pbts -o ../web/src/components/compiled.d.ts ../web/src/components/compiled.js
该方法脚本已经写在了本文完整示例代码的/packages/server/package.json
文件中
代码实现
<template>
<div style="width: 100%; height: 200px; background: #d3d3d3">
<code>{{ messageRef }}</code>
<button @click="sendMsg"> 发送 </button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Message } from './compiled'; // 使用protobufjs-cli编译出来的包
const messageRef = ref('');
// 创建 WebSocket 连接
const ws = new WebSocket('ws://localhost:8080/');
// 监听 WebSocket 连接成功事件
ws.addEventListener('open', () => {
console.log('WebSocket connected1!');
// 序列化消息对象,并将其发送给服务器
const buffer = Message.encode({ text: '客户端2连接了' }).finish();
ws.send(buffer);
});
// 监听 WebSocket 收到服务器发送过来的消息事件
ws.addEventListener('message', async (event) => {
// 解析二进制数据为 Protobuf 消息
const blob: Blob = event.data;
// Uint8Array 接收的是arrayBuffer对象这里一定要注意如果是Blob格式的数据一定要先转为arrayBuffer
const buffer = await blob.arrayBuffer();
const data = new Uint8Array(buffer);
const message = Message.decode(data);
console.log(`Receive message from server: ${JSON.stringify(message)}`);
// 更新视图显示收到的消息内容
messageRef.value = message.text;
});
// 监听 WebSocket 出错事件
ws.addEventListener('error', (event) => {
console.error(event);
});
// 监听 WebSocket 关闭事件
ws.addEventListener('close', (event) => {
console.warn(event);
});
const sendMsg = () => {
// 序列化消息对象,并将其发送给服务器
const buffer = Message.encode({ text: '我是客户端2' }).finish();
ws.send(buffer);
};
</script>
总结
以上就是vue3项目中传输protobuf数据的基本使用方法,仅供参考,如果有问题请留言评论。
更多推荐
已为社区贡献2条内容
所有评论(0)