前言

基于Http通信的游戏服务器和客户端一般首选JSON作为数据传输格式,通信参数校验是很琐碎的事。往往一些人为利用的BUG都与没有正确的参数校验,比如扣钱的参数传输负数等。人为做消息请求做参数校验又不能避免漏掉参数校验,我们需要一套行之有效的参数校验框架。本文主要讲如何利用做消息字典做消息检验。 下文主要以物品使用item_use消息做案例

案例

通常的消息处理如下

/**
 * @description 物品使用
 * @param {Object} msg 消息体
 * @param {Number} msg.itemID 物品ID
 * @param {Number} msg.itemNum 物品数量
 * @param {Object} session 抽象连接对象
 * @param {Function} next 消息返回
 */
function item_use(msg, session, next) {
  if(msg.itemID === undefined || !Number.isFinite(msg.itemID) || msg.itemID < 0) {
    return next({retCode:'error param'});
  }
  if(msg.itemNum === undefined || !Number.isFinite(msg.itemNum) || msg.itemNum < 0) {
    return next({retCode:'error param'});
  }
  ...
}

此时参数还少,手写基本还OK,一旦参数10或者更多,相信你写这逻辑时,会吐的。

设计实现

msgCfg.json
{
  "comment" : {
    "消息名" : {
      "comment" : "备注",
      "param" : {}
    }
  },
  "val" : {
    "item_use" : {
      "comment" : "物品使用",
      "param" : {
        "itemID" : {
          "type" : "Number",
          "comment" : "物品ID"
        },
        "itemNum" : {
          "type" : "Number",
          "comment" : "物品数量"
        }
      }
    }
  }
}

创建一个JSON文件msgCfg.json作为消息字典,并在其中添加物品使用的消息,格式类似如上。写一个消息管理模块MsgMng.js,在消息收到和功能处理前进行参数校验(!不是在item_use内,是item_use调用前),基本逻辑如下。

function MsgMng () {
  this.msgParam = require('msgCfg.json').val;
}

/**
 * @description 参数校验
 * @param {Number} route
 * @param {Object} msg
 * @return {null | Number}
 */
MsgMng.prototype.paramCheck = function (route, msg) {
  let err = null;
  do {
    let param = this.msgParam[route];
    if(!param) {
      logger.info("msg: " + route + " not register");
      err = RetCode.HTTP_CODE_401;
      break;
    }
    for(let k in param) {
      let key = '' + k;
      let type = param[key]["type"];
      let value = msg[key];
      if(value === undefined || value === null || type !== value.constructor.name || (value.constructor === Number && (value < 0 || !Number.isFinite(value)))) {
        logger.info("msg: " + route + " param is:[%s], reqMsg is:[%s]", route, JSON.stringify(param), JSON.stringify(msg));
        err = RetCode.ERROR_REQUEST_PARAM;
        break;
      }
    }
  } while(false);
  return err;
};

这样新增消息只要在消息字典内配置好消息包名参数类型就能处理绝大多数参数校验的代码量了。

继续深挖

消息字典的用途不止这个简单的作用

  • 前后端对应消息作为标准
  • 消息功能和参数查询方便
  • 模块交接减少难度
  • NX点直接做为消息生成模板
  • 为每个参数配置测试模式值
  • 可以自己改造,具体参数注册校验函数
  • 自己想吧…

总结

不想盲婚哑嫁,消息字典应该是Http通讯必不可少的一部分。减少体力活,是一个合格的码农应该觉醒的意识。只有效率提升上去,才能搬更多的砖。