blog icon indicating copy to clipboard operation
blog copied to clipboard

根据Lua Table设计协议

Open hanxi opened this issue 10 years ago • 0 comments

Lua Protocol

使用Lua Table语法定义协议模板。

设计由来

使用Lua开发游戏已经有两年多了,最初接触到的网络交互协议是由老大设计的。只支持整数和字符串类型的数据,后面的主程添加了元素为Lua表的数组类型的数据。主要核心在于Buffer的存储形式:

  • 整数分int8,int16,int32,int64类型存储,
  • 整数前面有1byte表示正负数和整数位数,
  • 字符串则是前面存字符串的长度。
  • 序列化时不存储key,只存value。
  • 协议的序列化和反序列化都需要依靠协议模板,称之为schema-full(有模式的序列化方式)

添加新类型

我现在添加了表,浮点数,完整的数组。

  • 数组元素必须是同种类型,类似于C语言数组
  • 数组元素可以是任意支持的类型
  • 序列化数组时,先存数组的长度
  • 表的key必须是字符串
  • 导入协议结构时会将表的key排序存储
  • 序列化表则是每个元素按key的顺序逐个存储

定义协议语法

  • 使用Lua Table的语法
  • 根据默认值区分整数和浮点数
    • 整数:n==math.floor(n) 例如:1.0,1,2.00
    • 浮点数:n~=math.floor(n) 例如:1.1,0.1,1.23
  • 字符串:Lua的string类型
  • 表:只支持key为string类型的table
  • 数组:定义第一个元素
  • 如下完整示例:
local proto_struct = {
    tbl_data = {
        int_data = 0,
        float_data = 0.1,
        str_data = "default string",
        int_array = {1},
        float_array = {1.1},
        str_array = {""},
    },
    tbl_array = {
        {
            name = "tbl_array_element",
            id = 1,
        },
    },
}

Buffer格式

int 类型

  • (2bytes)[-255,+255]
sign 1byte 1byte
- 0xF1 0x00~0xFF
+ 0x01 0x00~0xFF
  • (3bytes)[-65535,-256],[+256,+65535]
sign 1byte 2byte
- 0xF2 0x0100~0xFFFF
+ 0x02 0x0100~0xFFFF
  • (5bytes)[-4294967295,-65536],[+65536,+4294967295]
sign 1byte 4byte
- 0xF3 0x00010000~0xFFFFFFFF
+ 0x03 0x00010000~0xFFFFFFFF
  • (9bytes)[-9223372036854775807,-4294967296],[+4294967296,+9223372036854775807] (因为受限于int64_t,所以不是uint64_t的最大值)
sign 1byte 8byte
- 0xF4 0x0000000100000000~0x7FFFFFFFFFFFFFFF
+ 0x04 0x0000000100000000~0x7FFFFFFFFFFFFFFF

string 类型(float类型转为string类型存储

len_of_string string
int string

array 类型

len_of_array element1 element2 ... elementn
int e1 e2 ... en

table 类型

按key排序依次存储

tbl = {
    a = 1,
    b = 2,
    c = "tbl",
}
a b c
1 2 tbl

协议模板的C数据结构

struct field {
    struct field *next;
    struct field_list *child;
    char type;
    char key[DEFAULT_STR_LEN];
    union {
        char str_value[DEFAULT_STR_LEN];
        int int_value;
    } default_value;
};

struct field_list {
    struct field *head;
    struct field *tail;
    int len;
};
// field 用于存储int/float/string,field_list用于存储array/table

代码已经开源了,在这里https://github.com/hanxi/lproto

hanxi avatar Feb 03 '15 14:02 hanxi