golang / creator js 實現使用 protobuf 進行數據交互

protobuf 是傳輸數據序列化的一個通用規則,相比xml和json更快更小。
本次使用的是proto3,3相比於2有一些特性上的不同,例如3默認了optional聲明。
所有字段都是可選賦值,這樣做是爲了兼容有些字段會在特定版本被廢棄,序列化時,沒有的字段不會被轉化。

caretor js 使用

編寫好proto文件,就可以使用protoc進行編譯了,creatorjs引用google-protobuf.js的時候會有問題,解決無果以後我決定使用protobufjs,使用protobufjs最好有npm環境來下載安裝,nodejs和npm的安裝這裏就不多介紹了。

  1. 安裝protobufjs

-g 是全局安裝,安裝完以後,找到目錄,配置好…/protobufjs/bin 環境變量,bin目錄下有兩個可執行文件 pbjs和pbts,是用來編譯proto文件的。使用protobufjs就不會用到protoc。

# npm install -g protobufjs

  1. 編譯proto文件
// game.proto
syntax = "proto3"

message Login {
	string username = 1;
	string password = 2;
	int32 uid = 3;
}

message LoginResult {
	string token = 1;
}

配置好環境變量,就使用pbjs編譯proto文件

# pbjs -t json-module game.proto > client.json
# pbjs -t static-module game.proto > clientProto.js

-t [params] 參數說明
json JSON representation
json-module JSON representation as a module
proto2 Protocol Buffers, Version 2
proto3 Protocol Buffers, Version 3
static Static code without reflection (non-functional on its own)
static-module Static code without reflection as a module

注意:不同參數導出的的文件類型不一樣。

  1. js中使用
// proto.js
const proto = require("clientProto")
module.exports = {
	// static-module
	proto: function(name, pwd) {
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function() {
			if (xhr.readystatus = 4 && xhr.status >= 200 && xhr.status < 300) {
				var b = stringToBytes(xhr.responseText); //這裏需要將字符串轉爲byte數組
				proto.LoginResult.decode(b);
			}
		}
		xhr.open("POST", "localhost:8080/login");
        m_xhr.setRequestHeader("Content-Type","application/x-protobuf");
        m_xhr.setRequestHeader("Accept","application/x-protobuf");
        if (m_xhr.overrideMimeType){
            //這個是必須的,否則返回的是字符串,導致protobuf解碼錯誤
            //具體見http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html
            m_xhr.overrideMimeType("text/plain; charset=x-user-defined");
        }
		var param = proto.Login.encode({username:name, password:pwd).finish();
		xhr.send(param);
	},
	
	// json-module, json文件沒使用,用過後補全
	proto2: function() {
		
	}
};

golang 使用

go使用的話,我用的是iris框架,這裏就舉例iris怎麼解析。

package main

import (
	"gameProto"
	"github.com/golang/protobuf/proto"
	"github.com/kataras/iris"
)

func main() {
	app := iris.New()
	app.Post("/login", loginHandler)
	app.Run(iris.Addr("0.0.0.0:8080"))
}

func ProtoUnmashal(data []byte, v interface{}) error {
	return proto.Unmashal(data, v.(proto.Message)) // proto解析方法
}

func loginHandler(c iris.Context) {
	login := &gameProto.Login{} // 這個是解析後go結構
	// 解析客戶端傳的參數
	if c.UnmarshalBody(login, iris.UnmarshalerFunc(ProtoUnmashal)); err != nil {
		return
	}
	// do something ...
	loginResult := &gameProto.LoginResult{}
	loginResult.Token = "zx7g9f8h79j80sh98af766"
	
	if b, err := proto.Mashal(loginResult); err != nil {
		return
	} else {
		c.Write(b)
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章