协议响应设计
无论是 Web|Protbuf 服务端响应给客户端都基本需要对协议进行关联响应, 比如 Web 响应给数据(内部的 status
用于客户端索引错误处理):
// 客户端请求转发给内部让其转发到指定proto对象
{
// 标识请求的请求控制器
"proto": 10059,
"args": {
"username": "meteorcat",
"password": "meteorcat",
}
}
// 服务端响应给客户端响应协议
{
"status": 10037,
"message": "failed by username",
"data": {}
}
而 GoogleProtobuf 也虽然不需要带上 status, 但是需要在客户端|服务端采用 KEY-VALUE 方式做哈希索引:
--- 这里做类似Lua挂载查询
--- 常规都是以哈希表方式让其客户端|服务端启动时候加载
protocols = {}
protocols[10023] = LoginRequestProto.New()
protocols[10024] = LoginResponseProto.New()
--- 后续直接调用其内部句柄对象解析协议即可
所以协议关联是很重要的, 否则后续请求协议数据多起来特别庞大也不好管理, 所以需要全局的协议管理器方便注入处理;
但是注册协议时候最大问题就是协议分类, 功能分类譬如 玩家分类(User-Login|Register)|公告分类(Notice-List|Readed),
这种时候就需要对协议做分类方便类目管理, 这推荐采用整除法做协议管理分组:
--- 正规的协议采用 `xxxyyy` 格式的 int 类型
--- 比如设定用户信息类 100, 而他分类当中可以 获取信息(1)/修改昵称(2)
--- 剩下设定场景游戏类 200, 而其分类当中可以 加入房间(1)/离开房间(2)
local user_group = 100
local user_get_info = 1
local user_change_nickname = 2
-- 打包成int
local user_mask = user_group * 1000 -- 转换成 100,000
local user_get_info_proto = user_mask + user_get_info -- 打包成 100,001, 后三位用于识别子分类
local user_change_nickname_proto = user_mask + user_change_nickname -- 打包成 100,002
-- 解包出类型和具体协议
local dec_mask = tonumber(user_get_info_proto / 1000) -- 整除掉标识, 获取到分类 100
local dec_id = user_get_info_proto - (dec_mask * 1000) -- 提取出的具体协议值 1
这种方法直接利用简单的加减乘除处理, 在性能上面占据优势且跨平台处理也方便移植, 所以包装协议可以直接处理好封装成哈希表处理.