Skip to content

用于游戏前后端通信的自定义二进制协议

License

Notifications You must be signed in to change notification settings

ErlGameWorld/genProto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

genProto

用于根据自定义的协议文件生成 erl, c#, lua的序列化和反序列化代码

Build

rebar3 escriptize  

Use

rebar3 escriptize生成的genProto genPtoto.cmd 在_build/default/bin下面 将其复制到可以被搜索的执行路径或者工作目录
genProto ProtoInputDir Lang("erl", "lua", "cs") OutDir(erl 存在两个输出目录 头文件和Erl文件的输出目录 lua和cs只有一个输入目录)
eg: genProto:convertDir(["./proto", "erl", "./test/erl/", "./test/erl/", "lua", "./test/lua/", "cs", "./test/cs/"]).

简单描述

可用于erlang游戏或者erlang其他网络应用的协议解析编码解码的项目,具有较高的编码解码性能,
协议文件存放在proto目录 文件名为 Message protocol definition file的缩写 mpdf。

支持的数据类型

erl: int8 uint8 int16 uint16 int32 uint32 int64 uint64 integer number(整数或者浮点数) string float(32位浮点数) double(64位浮点数) bool record(struct) 以及上面类型的列表
lua: int8 uint8 int16 uint16 int32 uint32 int64 uint64 integer number(整数或者浮点数) string float(32位浮点数) double(64位浮点数) bool record 以及上面类型的列表
c#: int8 uint8 int16 uint16 int32 uint32 int64 uint64 string float(32位浮点数) double(64位浮点数) bool record 以及上面类型的列表

各种数据类型的编码格式(字节序大端存储, string用utf8编码)

int8:               直接存8bit的值       
uint8:              直接存8bit的值  
int16:              直接存16bit的值
uint16:             直接存16bit的值
int32:              直接存32bit的值
uint32:             直接存32bit的值
int64:              直接存64bit的值
uint64:             直接存64bit的值
integer:            如果值在int8范围区间: 8bit的Tag 值为8 + 8bit的值; 如果值在int16范围区间: 8bit的Tag 值为16 + 16bit的值; 如果值在int32范围区间: 8bit的Tag 值为32 + 32bit的值; 如果值在int64范围区间: 8bit的Tag 值为64 + 64bit的值;
number:             如果值是整数则:编码规则同 integer类型; 如果是浮点数: 如果值在float32范围区间  8bit的Tag 值为33 + 32bit的值; 如果值在float64范围区间  8bit的Tag 值为65 + 64bit的值;    
string:             16bit的Tag 存放的字符串长度(长度不包含字符串结尾符) + 字符串的内容(内容不包含结字符串尾符号)         
float:               直接存放32bit的值
double:             直接存放64bit的值
bool:               占位8bit 如果为true 则存放的值为1 否则存放的值为0
record(struct):     如果是undefined 或者是空指针 则 8bit Tag 值为0, 否则 8bit的tag 值为1 + record的二进制数据
list_+上面的数据类型的时候: 16bit的tag 用于存放 数组的长度 + 按数组顺序序列化每个元素的值的二进制数据(注意:如果列表类型为record(struct) 每个值序列化的时候并不会加 8bit的tag, 直接存record的二进制数据)

关于消息接收转发解码和发送

erlang通常会将接收到的消息由网关进程转发给其他工作进程, 建议先匹配消息id, 然后转发二进制消息到工作进程,然后由工作进程解码再处理
同时广播消息可先编码成二进制之后再广播, 避免重复编码

erl部分简单性能测评

主要和gpb做简单对比测试
gpb测试相关文件在test/gpb目录下
测试协议:
gpb:
message test {
 	required string aa = 1;
 }

message phoneNumber {
   	required test number = 1;
   	required int32 type  = 2;
}

message person {
  	required string name = 1;
  	required int32 integer = 2;
  	optional string email = 3;
  	repeated phoneNumber phone = 4;
}

message addressBook {
	repeated  person person1 = 1;
	repeated  person others = 2;
}

message tint32 {
    required int32 int1 = 1;
    required int32 int2 = 2;
    required int32 int3 = 3;
    required int32 int4 = 4;
    required int32 int5 = 5;
    required int32 int6 = 6;
    required int32 int7 = 7;
    required int32 int8 = 8;
    required int32 int9 = 9;
    required int32 int10 = 10;
}
genProto用的协议:

test {
	string aa;
}

phoneNumber{
    test number;
    int32 type;
}

person{
	string name;
	int32 id;
	string email;
	list[phoneNumber] phone;
}

addressBook {
    list[person] person;
	list[person] other;
}

tint32{
    int32 int1;
    int32 int2;
    int32 int3;
    int32 int4;
    int32 int5;
    int32 int6;
    int32 int7;
    int32 int8;
    int32 int9;
    int32 int10;
}
测试运行三次 每次100万次循环
tint32 gpb-------->>
    tint32 encode:
        > timer:tc(mytest, encode_int32, [1000000]).
        {9625000,ok}
        > timer:tc(mytest, encode_int32, [1000000]).
        {9000000,ok}
        > timer:tc(mytest, encode_int32, [1000000]).
        {9969000,ok}
        
    tin32 decode:
        > timer:tc(mytest, decode_int32, [1000000]).
        {6217994,ok}
        > timer:tc(mytest, decode_int32, [1000000]).
        {6187993,ok}
        > timer:tc(mytest, decode_int32, [1000000]).
        {6265994,ok}
        
    size:
        > BTInt32 = mytest:decode_int32(1).
        <<8,1,16,255,255,255,255,255,255,255,255,255,1,24,128,1,
          32,128,255,255,255,255,255,255,255,255,1,40,128,...>>
        31> byte_size(BTInt32).              
        74
tint32 genProto ------->>
    tint32 encode:
        > timer:tc(test, encode_int32, [1000000]).
        {328999,ok}
        > timer:tc(test, encode_int32, [1000000]).
        {328000,ok}
        > timer:tc(test, encode_int32, [1000000]).
        {344000,ok}
    
    tint32 decode:
        > timer:tc(test, decode_int32, [1000000]).
        {328000,ok}
        > timer:tc(test, decode_int32, [1000000]).
        {328000,ok}
        > timer:tc(test, decode_int32, [1000000]).
        {329000,ok}
        
    size:
        > BTInt32 = test:decode_int32(1).  
        <<0,11,0,0,0,1,255,255,255,255,0,0,0,128,255,255,255,128,
          0,1,0,0,255,255,0,0,125,43,117,...>>
        > byte_size(BTInt32).
        42
===============================================================================
===============================================================================        
addressBook gpb-------->>
    addressBook encode:
        > timer:tc(mytest, encode_addressBook, [1000000]).
        {9108990,ok}
        > timer:tc(mytest, encode_addressBook, [1000000]).
        {8999991,ok}
        > timer:tc(mytest, encode_addressBook, [1000000]).
        {9031991,ok}

    addressBook decode:
        > timer:tc(mytest, decode_addressBook, [1000000]).
        {5702995,ok}
        > timer:tc(mytest, decode_addressBook, [1000000]).
        {5764994,ok}
        > timer:tc(mytest, decode_addressBook, [1000000]).
        {5718995,ok}
    size:
        > BAddr = mytest:decode_addressBook(1).
        <<10,43,10,5,65,108,105,99,101,16,144,78,34,15,10,11,10,9,
          49,50,51,52,53,54,55,56,57,16,1,...>>
        > byte_size(BAddr).                    
        75
addressBook genProto -------->>
    addressBook encode:
        > timer:tc(test, encode_addressBook, [1000000]).
        {4186995,ok}
        > timer:tc(test, encode_addressBook, [1000000]).
        {4202996,ok}
        > timer:tc(test, encode_addressBook, [1000000]).
        {4202996,ok}
    addressBook decode:
        > timer:tc(test, decode_addressBook, [1000000]).
        {2749997,ok}
        > timer:tc(test, decode_addressBook, [1000000]).
        {2812997,ok}
        > timer:tc(test, decode_addressBook, [1000000]).
        {2812997,ok}
    size:
        BAddr = test:decode_addressBook(1).  
        <<0,4,0,2,0,5,65,108,105,99,101,0,0,39,16,0,0,0,2,1,0,9,
          49,50,51,52,53,54,55,...>>
        67> byte_size(BAddr). 
        83

About

用于游戏前后端通信的自定义二进制协议

Resources

License

Stars

Watchers

Forks

Packages

No packages published