websocket ( go srv / JS client) 使用flatbuffers 交互 (Fasthttp系列之3)
2013 年 5 月 20 日
为某个开源项目增加 websocket 对接, 写了这个示例
代码中 javascript 对 flatbuffers 的序列化/反序列化, 查了一天资料, 嗯哼, 最终完成了.
看代码吧………
代码中 javascript 对 flatbuffers 的序列化/反序列化, 查了一天资料, 嗯哼, 最终完成了.
看代码吧………
1. 使用代码库
示例代码使用了以下开源库
- fasthttp
- fasthttp router
-
fastws
—- fasthttp 实现的 websocket 库 -
flatbuffers
—- flatbuffers 高效反序列化通用库, 用在 go语言/javascript -
websockets/ws
—- javascript websocket 通用库
1. flatbuffers IDL 示例
xone.fbs 示例来自 www.cnblogs.com/sevenstar/p…
, 感谢!!
namespace xone.genflat; table LoginRequest{ msgID:int=1; username:string; password:string; } table LoginResponse{ msgID:int=2; uid:string; } //root_type非必须。 //root_type LoginRequest; //root_type LoginRespons 复制代码
2. flatc 编译代码
生成 javascript
flatc -s --gen-mutable ./*.fbs 复制代码
生成 golang
flatc --go --gen-object-api --gen-all --gen-compare --raw-binary ./*.fbs 复制代码
3. 主要代码说明
./cmd/wsserver/main.go ----- websocket server ./cmd/wsclient/main.go ----- websocket client ./ws/... ------------------- websocket go code for websocket handler and websocket client ./jsclient/ws.js ---------- javascript client code , please check-out package.json for depends 复制代码
4. javascript 序列化/反序列化
请注意代码注释中的——— 特别注意这一行
// ------------ ./jsclient/index.js const flatbuffers = require('./flatbuffers').flatbuffers; const xone = require('./xone_generated').xone; //Generated by `flatc`. //------------------------------------------- // serialized //------------------------------------------- let b = new flatbuffers.Builder(1); let username = b.createString("zlssssssssssssh"); let password = b.createString("xxxxxxxxxxxxxxxxxxx"); xone.genflat.LoginRequest.startLoginRequest(b); xone.genflat.LoginRequest.addUsername(b, username); xone.genflat.LoginRequest.addPassword(b, password); xone.genflat.LoginRequest.addMsgID(b, 5); let req = xone.genflat.LoginRequest.endLoginRequest(b); b.finish(req); //创建结束时记得调用这个finish方法。 let uint8Array = b.asUint8Array(); // ------------- 特别注意这一行 console.log(uint8Array); // console.log(b.dataBuffer() ); //------------------------------------------- // un-serialized //------------------------------------------- let bb = new flatbuffers.ByteBuffer(uint8Array); //-------------- 特别注意这一行 let lgg = xone.genflat.LoginRequest.getRootAsLoginRequest(bb); console.log("username: ", lgg.username()); console.log("password", lgg.password()); console.log("msgID: ", lgg.msgID()); 复制代码
5. golang 中对 flatbuffers 的序列化/反序列化
// ------ ./apis/genflat/model.go func (a *LoginRequestT) Byte() []byte { b := flatbuffers.NewBuilder(0) b.Finish(LoginRequestPack(b, a)) return b.FinishedBytes() } func ByteLoginRequestT(b []byte) *LoginRequestT { return GetRootAsLoginRequest(b, 0).UnPack() } // ------- ./apis/genflat/model_test.go func TestLoginRequestT_Byte(t *testing.T) { as := assert.New(t) // serialized l := &LoginRequestT{ MsgID: 1, Username: "1", Password: "1", } b := l.Byte() // un-serialized c := ByteLoginRequestT(b) if l.MsgID > 0 { fmt.Println(" id > ", c.MsgID, " u > ", c.Username, " pw > ", c.Password) } as.Equal(l.Password, c.Password) } 复制代码
6. websocket 代码
ws.onmessage = (event) => { //------------------------------------------------------------------- // read from websocket and un-serialized via flatbuffers //-------------------------------------------------------------------- let aa = str2ab(event.data); let bb = new flatbuffers.ByteBuffer(aa); let lgg = xone.genflat.LoginRequest.getRootAsLoginRequest(bb); let pw = lgg.password(); if (typeof pw === 'string') { console.log("----------------------------------------------"); console.log("username: ", lgg.username()); console.log("password", lgg.password()); console.log("msgID: ", lgg.msgID()); } else { console.log("================================="); console.log(event.data); } // console.log(`Roundtrip time: ${Date.now() }` , ab2str(d )); setTimeout(function timeout() { //------------------------------------------------------------------- // serialized via flatbuffers and send to websocket //-------------------------------------------------------------------- let b = new flatbuffers.Builder(1); let username = b.createString("zlssssssssssssh"); let password = b.createString("xxxxxxxxxxxxxxxxxxx"); xone.genflat.LoginRequest.startLoginRequest(b); xone.genflat.LoginRequest.addUsername(b, username); xone.genflat.LoginRequest.addPassword(b, password); xone.genflat.LoginRequest.addMsgID(b, 5); let req = xone.genflat.LoginRequest.endLoginRequest(b); b.finish(req); //创建结束时记得调用这个finish方法。 let uint8Array = b.asUint8Array(); ws.send(uint8Array); }, 500); }; function str2ab(str) { let array = new Uint8Array(str.length); for (let i = 0; i < str.length; i++) { array[i] = str.charCodeAt(i); } return array } 复制代码