websocket ( go srv / JS client) 使用flatbuffers 交互 (Fasthttp系列之3)

为某个开源项目增加 websocket 对接, 写了这个示例
代码中 javascript 对 flatbuffers 的序列化/反序列化, 查了一天资料, 嗯哼, 最终完成了.
看代码吧………

1. 使用代码库

示例代码使用了以下开源库

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
}

复制代码