【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))
相关推荐
山河木马10 小时前
矩阵专题3-怎么创建投影矩阵(uProjectionMatrix)
javascript·webgl·计算机图形学
泯泷12 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
泯泷12 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全
朦胧之13 小时前
页面白屏卡住排查方法
前端·javascript
犇驫聊AI13 小时前
Chrome DevTools MCP + Claude Code 自定义skills生成接口代码生成器
前端·javascript
kyriewen14 小时前
别再这样写 async/await 了:我在 Code Review 中见过最多的 8 个错误
前端·javascript·面试
用户2986985301418 小时前
在 React 中使用 JavaScript 将 Excel 转换为 SVG
前端·javascript·react.js
labixiong19 小时前
手写Promise--微任务、静态方法、async/await 全搞懂(三)
前端·javascript
铁皮饭盒20 小时前
3行代码搞定页面截图,Bun.WebView真的简单
javascript
kyriewen1 天前
我手写了一个 EventEmitter,面试官追问了 6 个问题——第 4 个我没答上来
前端·javascript·面试