【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 小时前
JavaScript 内存与引用:深究深浅拷贝、垃圾回收与 WeakMap/WeakSet
开发语言·javascript·ecmascript
cyclv4 小时前
无网络地图展示轨迹,地图瓦片下载,绘制管线
前端·javascript
HIT_Weston6 小时前
41、【Agent】【OpenCode】本地代理分析(五)
javascript·人工智能·opencode
前端Hardy7 小时前
前端必看!LocalStorage这么用,再也不踩坑(多框架通用,直接复制)
前端·javascript·面试
前端Hardy7 小时前
前端必看!前端路由守卫这么写,再也不担心权限混乱(Vue/React通用)
前端·javascript·面试
竹林8187 小时前
从ethers.js迁移到Viem:我在重构DeFi前端时踩过的那些坑
前端·javascript
前端郭德纲7 小时前
JavaScript Object.freeze() 详解
开发语言·javascript·ecmascript
希望永不加班8 小时前
SpringBoot 静态资源访问(图片/JS/CSS)配置详解
java·javascript·css·spring boot·后端
m0_738120728 小时前
渗透基础知识ctfshow——Web应用安全与防护(第一章)
服务器·前端·javascript·安全·web安全·网络安全
持续前行8 小时前
通过 npm 下载node_modules 某个依赖 ;例如 下载 @rollup/rollup-linux-arm64-gnu
前端·javascript·vue.js