14

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

 4 years ago
source link: https://studygolang.com/articles/25793
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

为某个开源项目增加 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
}

复制代码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK