目录
- 说在前面
- 场景
- 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)// startfbs.MsgWebsocketStart(builder)fbs.MsgWebsocketAddCmd(builder, cmd)fbs.MsgWebsocketAddData(builder, off)// endend := 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:breakcase 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))