当前位置: 首页 > news >正文

KBEngine 服务器端-loginapp-协议构建、解析执行

为什么80%的码农都做不了架构师?>>> hot3.png

前文KBEngine 客户端登录-loginapp-协议加载提到服务器端 loginapp 通过加载 res/server/messages_fixed.xml 来构建协议,这里就详细讲一下这个协议的加载和构建过程。

宏宏宏

由于 C++ 是静态语言,不能像 js 一样通过函数名字符串来直接执行函数,所以将 messageId 映射到可执行函数的复杂性大大提升;KBEngine 使用了一系列精巧的「宏」来解决这个问题。

为了叙述方便,我把需要通过 messageId 来映射执行的函数称为「协议函数」,以区分普通的函数。

loginapp 的宏,统一在 loginapp_interface_macros.h 中声明,在 loginapp_interface.h 中使用。我把 loginapp_interface.h 进行简化,只保留两个函数:importClientMessage,login。


可以看到,上面截图分为 3 个部分

  • 第 5 、14 行是一个完整的宏
  • 第 8 行是将 importClientMessages 转化为「协议函数」的宏
  • 第 11、12 行是将 login 转化为「协议函数」的宏

namespace LoginappInterface


上图是将本文第一张图 5、14 行宏展开后的代码,这对 BEGIN/END 宏,不光是定义了一个 namespace,更重要的是,声明了 messageHandlers,这里面就存放了所有映射好的「协议函数」

importClientMessages

上图是将本文第一张图中第 8 行展开后的代码,由几个重要的逻辑组成:

  • 30~38 行,声明了一个 MessageHandler 的派生类,这个类的 handle 函数,是个 virtual 函数,执行的就是 Loginapp::importClientMessages。(KBEngine 架构的 loginapp 是单例,所以这里才能这么玩,否则没法对应到想要执行的函数所在对象)
  • 40~45 行,将调用 messangeHandlers.add 函数,完成 messangeId 到 importClientMessagesLoginappMessagehandler0 类对象的映射;
    此后,就可以通过 messageId 找到一个 MessangeHandler 对象指针,然后执行他的 handle 函数,由于这是 virtual 函数,真正执行的就是 importClientMessagesLoginappMessagehandler0 中的 handle 函数,也就是 Loginapp::importClientMessages 函数
  • 47 行,保存添加过映射关系的 MessangeHandlers;这个主要是为了其他组件调用,如 baseapp 可以通过(*pBundle).newMessage( Loginapp::importClientMessages);  这样的形式调用到这个函数
  • 49~69 行 importClientMessages 函数的参数对象,ARGS0 表示 importClientMessages 函数不需要参数。

login

上图是将本文第一张图中第 11、12 行展开后的代码,由几个重要的逻辑组成:

  • 28 行,使用 "Loginapp::login" 作为 messageHandlers.pushExposedMessage 的参数,即这个函数将会被导出到客户端,以便客户端调用。
  • 30~68 行,与前面逻辑基本一样,这里不再解释。
  • 主要看两个图的第 37 行的区别,可以看到,LOGINAPP_MESSAGE_DECLARE_ARGS0 宏展开后,这行除了 Channel,没有其他参数;LOGINAPP_MESSAGE_DECLARE_STREAM 宏展开后,除了 Channel,还有一个 MemoryStream 参数,表示这个函数的参数需要从流中读取。

MessageHandlers::add

add 函数,将"Loginapp::login" 形式的函数名转成 messageId,并与 MessageHandler* 建立映射关系。

上图,150~171 行,先通过 FixedMessage 判断("Loginapp::login")函数名是否在 res/server/messages_fixed.xml 中声明过,如果声明过,就取声明的 id 作为 messageId,否则就循环找到一个未被使用的 id。


上图,180 行建立 messageId 到 MessageHandler* 的映射。msgHandlers_ 是一个 map。


上图,50 行,可以看到 FixMessages 加载的配置文件地址,就是我们一直提到的 messages_fixed.xml。

协议执行

通过上面的宏,我们可以看到 messageId -> 「协议函数」的映射关系已经建立起来,那么这个在什么时候回被调用到呢?


上图是 login 函数的调用堆栈,我们来看一下 Loginapp::handleMainTick 函数


可以看到,112 行的参数是 &LoginappInterface::messageHandlers,也就是在宏里已经填好 messageId -> 「协议函数」映射关系的全局变量。

真正的执行逻辑,在 PacketReader::processMessages 函数里。

如上图,先在 81 行取到 messageId,然后在 85 行,在 messageHandlers 里 find (简单的 map 的查找即可)到对应的 MessageHandler,再调用 handle 函数,按我们前面的分析,handle 函数里面会调用到 messageId 对应的 「协议函数」。

至此,整个 loginapp 服务器端协议从构建到解析执行的整个过程解释完成。

后记

KBEngine 支持的几种宏说明

  • LOGINAPP_MESSAGE_DECLARE_ARGS0,  「协议函数」有 0 个参数
  • LOGINAPP_MESSAGE_DECLARE_ARGS1,  「协议函数」有 1 个参数
  • LOGINAPP_MESSAGE_DECLARE_ARGS2,  「协议函数」有 2 个参数
  • LOGINAPP_MESSAGE_DECLARE_STREAM,「协议函数」参数为 MemoryStream
  • LOGINAPP_MESSAGE_EXPOSED,「协议函数」将被暴露给客户端,即会在 importClientMessages 中发送给客户端

转载于:https://my.oschina.net/zenglingfan/blog/617369

相关文章:

  • android 三级菜单 BaseExpandableListAdapter
  • [linux]linux命令学习-netstat
  • 内容观察者
  • iOS学习笔记19-抽屉MMDrawerController使用
  • thrift 远程服务调用 简单示例
  • 中国移动短信网关错误代码汇总(完整版)
  • 编译安装 apache+mysql+php 详细步骤
  • OC基础--常用类的初步介绍与简单实用之NSString
  • iOS UIViewController生命周期控制
  • Java 异常处理的 9 个最佳实践
  • Linux运维工程师面试题第九套
  • js判断是否是用微信浏览器打开
  • 147. Insertion Sort List
  • java值类型和引用类型
  • 如何查看oracle表空间是否自动扩展
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【技术性】Search知识
  • Babel配置的不完全指南
  • Bytom交易说明(账户管理模式)
  • docker容器内的网络抓包
  • iOS | NSProxy
  • JS函数式编程 数组部分风格 ES6版
  • MD5加密原理解析及OC版原理实现
  • Node 版本管理
  • 笨办法学C 练习34:动态数组
  • 从重复到重用
  • 后端_ThinkPHP5
  • 聚簇索引和非聚簇索引
  • 用Python写一份独特的元宵节祝福
  • Python 之网络式编程
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 整理一些计算机基础知识!
  • !!Dom4j 学习笔记
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #pragma once与条件编译
  • #单片机(TB6600驱动42步进电机)
  • $refs 、$nextTic、动态组件、name的使用
  • (八)Flask之app.route装饰器函数的参数
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二)Linux——Linux常用指令
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (过滤器)Filter和(监听器)listener
  • (十八)三元表达式和列表解析
  • (顺序)容器的好伴侣 --- 容器适配器
  • (原創) 未来三学期想要修的课 (日記)
  • (转)Unity3DUnity3D在android下调试
  • (转)四层和七层负载均衡的区别
  • .NET 5种线程安全集合
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .Net CoreRabbitMQ消息存储可靠机制
  • .Net Core缓存组件(MemoryCache)源码解析
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性