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)
	}
}
上一篇:scikit-learn决策树算法类库使用小结


下一篇:用R语言进行数据可视化的综合指南(一)