【typescript/flatbuffer】在websocket中使用flatbuffer

目录

说在前面

  • 操作系统:Windows11
  • node版本:v18.19.0
  • typescript flatbuffer版本:24.3.25

场景

  • 服务器(本文为golang+gin)与前端通信时使用flatbuffer进行序列化与反序列化
  • 通信协议为websocket

fbs

  • 测试使用的flatbuffer schema如下:

    c 复制代码
    namespace fbs;
    
    enum Command:int32 {
        None        = 0,
        Mesh        = 1,
        PhysXml     = 2,
    }
    
    table MsgWebsocket {
        cmd:    Command;
        data:   [ubyte];
    }

    相对比较简单,唯一复杂的地方在于使用了一个byte数组

  • 获取flatc

    github release页面下载对应版本的二进制程序,这里下载了windows版本的

    解压后得到flatc.exe

  • 生成golang代码

    shell 复制代码
    bin\flatc.exe -g ws.fbs 
    # bin\flatc.exe -g -o ..\ ws.fbs
    # -o 制定生成目录 
  • 生成typescript代码

    shell 复制代码
    bin\flatc.exe --ts ws.fbs 

服务器代码

  • 反序列化前端发来的数据:

    go 复制代码
    func handleFbMsg(p []byte, ws *websocket.Conn) {
    	// GetRootAsMsgWebsocket为生成的函数,用于解析二进制数据
    	msg := fbs.GetRootAsMsgWebsocket(p, 0)
    	switch msg.Cmd() {
    	case fbs.CommandMesh:
    		mesh, err := os.ReadFile("./a.bin")
    		if err == nil {
    			ws.WriteMessage(websocket.BinaryMessage, buildByteFbMsg(msg.Cmd(), mesh))
    		} else {
    			fmt.Println(err)
    		}
    	case fbs.CommandPhysXml:
    	}
    }
  • 序列化要发给前端的数据:

    go 复制代码
    func buildByteFbMsg(cmd fbs.Command, b []byte) []byte {
    	builder := flatbuffers.NewBuilder(len(b) + 4)
    
    	off := builder.CreateByteVector(b)
    	// start
    	fbs.MsgWebsocketStart(builder)
    	fbs.MsgWebsocketAddCmd(builder, cmd)
    	fbs.MsgWebsocketAddData(builder, off)
    	// end
    	end := fbs.MsgWebsocketEnd(builder)
    	builder.Finish(end)
    
    	nb := builder.FinishedBytes()
    	return nb
    }

    flatbuffer的序列化过程比较复杂,具体的例子可以参考官方文档

前端typescript代码

  • 反序列化,代码和后端类似:

    typescript 复制代码
    private handleSceneMsg(data: any) {
        var buffer = new ByteBuffer(new Uint8Array(data.data))
        var msg = MsgWebsocket.getRootAsMsgWebsocket(buffer)
        switch (msg.cmd()) {
            case Command.Mesh:
                break
            case Command.PhysXml:
                break
        }
    }
  • 序列化:

    typescript 复制代码
    public ok(cmd: Command) {
        const builder = new flatbuffers.Builder(0)
        MsgWebsocket.startMsgWebsocket(builder)
        MsgWebsocket.addCmd(builder, cmd)
        const end = MsgWebsocket.endMsgWebsocket(builder)
        builder.finish(end)
        const data = builder.asUint8Array()
        
        this._socket.send(data)
    }

问题

  • 如何序列化?
    参考官方文档,说实在的,fb的序列化是目前见过最麻烦的了,其他大部分都是一个函数搞定

  • 前端反序列化出错

    typescript 复制代码
    var buffer = new ByteBuffer(data.data)

    最开始是这行代码,data是websocket的事件,data.data实际上是arraybuffer,需要转换一下,

    typescript 复制代码
    var buffer = new ByteBuffer(new Uint8Array(data.data))
相关推荐
学不会•1 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS2 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder6 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。7 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客7 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js