目录
- 说在前面
- 场景
- fbs
- 服务器代码
- 前端typescript代码
- 问题
说在前面
- 操作系统:Windows11
- node版本:v18.19.0
- typescript flatbuffer版本:24.3.25
场景
- 服务器(本文为golang+gin)与前端通信时使用
flatbuffer
进行序列化与反序列化 - 通信协议为
websocket
fbs
-
测试使用的
flatbuffer schema
如下: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
代码bin\flatc.exe -g ws.fbs # bin\flatc.exe -g -o ..\ ws.fbs # -o 制定生成目录
-
生成
typescript
代码bin\flatc.exe --ts ws.fbs
服务器代码
- 反序列化前端发来的数据:
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: } }
- 序列化要发给前端的数据:
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代码
- 反序列化,代码和后端类似:
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 } }
- 序列化:
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
的序列化是目前见过最麻烦的了,其他大部分都是一个函数搞定 - 前端反序列化出错
最开始是这行代码,data是websocket的事件,var buffer = new ByteBuffer(data.data)
data.data
实际上是arraybuffer
,需要转换一下,var buffer = new ByteBuffer(new Uint8Array(data.data))