Zinx框架-游戏服务器开发002:按照三层结构模式重构代码功能-待续

本文主要是介绍Zinx框架-游戏服务器开发002:按照三层结构模式重构代码功能-待续,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1 Zinx框架总览
  • 2 三层模式的分析
  • 3 三层重构原有的功能 - 头文件
    • 3.1 通道层Stdin和Stdout类
      • 3.1.2 StdInChannel
      • 3.1.2 StdOutChannel
    • 3.2 协议层CmdCheck和CmdMsg类
      • 3.2.1 CmdCheck单例模式
        • 3.2.1.1 单例模式
        • 3.2.1.2 * 命令识别类向业务层不同类别做分发
      • 3.2.2 CmdMsg自定义用户信息类,继承UserData
    • 3.3 业务层:回显类, 输出通道控制类, 日期前缀管理类
      • 3.3.1 回显对象EchoRole
      • 3.3.2 控制输入输出
      • 3.3.3 日期管理类

1 Zinx框架总览

在这里插入图片描述

2 三层模式的分析

在这里插入图片描述

3 三层重构原有的功能 - 头文件

三层结构重构原有功能

  1. 自定义消息类,继承UserData,添加一个成员变量szUserData
  2. 定义多个Role类继承Irole,重写ProcMsg函数,进行不同处理
  3. 定义protocol类,继承Iprotocol,重写四个函数,两个函数时原始
    数据和用户数据之间的转换;另两个用来找消息处理对象和消息发
    送对象。
  4. 定义channel类,继承Ichannel,在getnextinputstage函数中返回协
    议对象

3.1 通道层Stdin和Stdout类

通道类,派生自基础处理者类,提供基于系统调用的数据收发功能
一般地,用户应该根据处理的文件(信息源)不同而创建通道类的子类或选用合适的实用类(已经提供的通道类子类)来完成系统级文件IO
在这里插入图片描述

class StdInChannel :public Ichannel
{
public:StdInChannel();virtual ~StdInChannel();// 通过 Ichannel 继承virtual bool Init() override;virtual bool ReadFd(std::string& _input) override;virtual bool WriteFd(std::string& _output) override;virtual void Fini() override;virtual int GetFd() override;virtual std::string GetChannelInfo() override;virtual AZinxHandler* GetInputNextStage(BytesMsg& _oInput) override;
};class StdOutChannel :public Ichannel
{// 通过 Ichannel 继承virtual bool Init() override;virtual bool ReadFd(std::string& _input) override;virtual bool WriteFd(std::string& _output) override;virtual void Fini() override;virtual int GetFd() override;virtual std::string GetChannelInfo() override;virtual AZinxHandler* GetInputNextStage(BytesMsg& _oInput) override;
};

3.1.2 StdInChannel

bool StdInChannel::ReadFd(std::string& _input)
{cin >> _input;return true;
}bool StdInChannel::WriteFd(std::string& _output)
{return false;
}int StdInChannel::GetFd()
{return 0;
}std::string StdInChannel::GetChannelInfo()
{return "stdin";
}AZinxHandler* StdInChannel::GetInputNextStage(BytesMsg& _oInput)
{/*返回协议对象*/return CmdCheck::GetInstance();
}

3.1.2 StdOutChannel

bool StdOutChannel::ReadFd(std::string& _input)
{return false;
}bool StdOutChannel::WriteFd(std::string& _output)
{cout << _output << endl;return true;
}int StdOutChannel::GetFd()
{return 1;
}std::string StdOutChannel::GetChannelInfo()
{return "stdout";
}AZinxHandler* StdOutChannel::GetInputNextStage(BytesMsg& _oInput)
{return nullptr;
}

3.2 协议层CmdCheck和CmdMsg类

3.2.1 CmdCheck单例模式

  1. 原始数据和业务数据相互函数,开发者重写该函数,实现协议
  2. 获取处理角色对象函数,开发者应该重写该函数,用来指定当前产生的用户数据消
  3. 获取发送通道函数,开发者应该重写该函数,用来指定当前字节流应该由哪个通道对象发出
class CmdCheck :public Iprotocol
{CmdCheck();virtual ~CmdCheck();static CmdCheck *poSingle;
public:// 通过 Iprotocol 继承/*原始数据和业务数据相互函数,开发者重写该函数,实现协议*/virtual UserData * raw2request(std::string _szInput) override;virtual std::string * response2raw(UserData & _oUserData) override;/*获取处理角色对象函数,开发者应该重写该函数,用来指定当前产生的用户数据消息应该传递给哪个角色处理*/virtual Irole * GetMsgProcessor(UserDataMsg & _oUserDataMsg) override;/*获取发送通道函数,开发者应该重写该函数,用来指定当前字节流应该由哪个通道对象发出*/virtual Ichannel * GetMsgSender(BytesMsg & _oBytes) override;static CmdCheck *GetInstance() {return poSingle;}std::string szOutChannel;
};
3.2.1.1 单例模式

构造全局唯一的协议对象

#include "CmdCheck.h"
#include "CmdMsg.h"
#include "EchoRole.h"
using namespace std;CmdCheck *CmdCheck::poSingle = new CmdCheck();
3.2.1.2 * 命令识别类向业务层不同类别做分发

通过是不是命令来进行区分:if (isCmd)

Irole * CmdCheck::GetMsgProcessor(UserDataMsg & _oUserDataMsg)
{szOutChannel = _oUserDataMsg.szInfo;if ("stdin" == szOutChannel){szOutChannel = "stdout";}/*根据命令不同,交给不同的处理role对象*/auto rolelist = ZinxKernel::Zinx_GetAllRole();auto pCmdMsg = dynamic_cast<CmdMsg *>(_oUserDataMsg.poUserData);/*读取当前消息是否是命令*/bool isCmd = pCmdMsg->isCmd;Irole *pRetRole = NULL;for (Irole *prole : rolelist){if (isCmd){auto pOutCtrl = dynamic_cast<OutputCtrl *>(prole);if (NULL != pOutCtrl){pRetRole = pOutCtrl;break;}}else{auto pDate = dynamic_cast<DatePreRole *>(prole);if (NULL != pDate){pRetRole = pDate;break;}}}return pRetRole;
}

3.2.2 CmdMsg自定义用户信息类,继承UserData

class CmdMsg :public UserData
{
public:/*成员变量表示要回显的字符串*/std::string szUserData;/*开启输出标志*/bool isOpen = true;/*该消息是命令*/bool isCmd = false;/*要加前缀*/bool needDatePre = false;CmdMsg();virtual ~CmdMsg();
};

3.3 业务层:回显类, 输出通道控制类, 日期前缀管理类

3.3.1 回显对象EchoRole

主要有init, procmsg,fini三个函数

#pragma once
#include <zinx.h>class EchoRole :public Irole
{
public:EchoRole();virtual ~EchoRole();// 通过 Irole 继承virtual bool Init() override;virtual UserData * ProcMsg(UserData & _poUserData) override;virtual void Fini() override;
};
  • 容易出错的点:参数一必须是一个堆对象
UserData * EchoRole::ProcMsg(UserData & _poUserData)
{/*写出去*/GET_REF2DATA(CmdMsg, input, _poUserData);CmdMsg *pout = new CmdMsg(input);ZinxKernel::Zinx_SendOut(*pout, *(CmdCheck::GetInstance()));return nullptr;
}

3.3.2 控制输入输出

  1. 写一个关闭输出的角色类,摘除输出通道或添加输出通道
  2. 在CmdMsg用户数据类中添加开关标志,是否是命令标志
  3. 在协议类中,根据输入字符串,设置开关标志和是否是命令的标志
  4. 在协议类分发消息时,判断是否是命令,是命令则发给关闭输出角 色类,否则发给回显角色类
class OutputCtrl :public Irole {// 通过 Irole 继承virtual bool Init() override;virtual UserData * ProcMsg(UserData & _poUserData) override;virtual void Fini() override;Ichannel *pOut = NULL;
};

3.3.3 日期管理类

class DatePreRole :public Irole {// 通过 Irole 继承virtual bool Init() override;virtual UserData * ProcMsg(UserData & _poUserData) override;virtual void Fini() override;bool needAdd = false;
};

这篇关于Zinx框架-游戏服务器开发002:按照三层结构模式重构代码功能-待续的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/338781

相关文章

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param

SpringBoot实现图形验证码的示例代码

《SpringBoot实现图形验证码的示例代码》验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用Hutool提供的小工具实现,本文介绍Sp... 目录项目创建前端代码实现约定前后端交互接口需求分析接口定义Hutool工具实现服务器端代码引入依赖获

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

利用Python在万圣节实现比心弹窗告白代码

《利用Python在万圣节实现比心弹窗告白代码》:本文主要介绍关于利用Python在万圣节实现比心弹窗告白代码的相关资料,每个弹窗会显示一条温馨提示,程序通过参数方程绘制爱心形状,并使用多线程技术... 目录前言效果预览要点1. 爱心曲线方程2. 显示温馨弹窗函数(详细拆解)2.1 函数定义和延迟机制2.2

SpringBoot+Vue3整合SSE实现实时消息推送功能

《SpringBoot+Vue3整合SSE实现实时消息推送功能》在日常开发中,我们经常需要实现实时消息推送的功能,这篇文章将基于SpringBoot和Vue3来简单实现一个入门级的例子,下面小编就和大... 目录前言先大概介绍下SSE后端实现(SpringBoot)前端实现(vue3)1. 数据类型定义2.

Python+wxPython开发一个文件属性比对工具

《Python+wxPython开发一个文件属性比对工具》在日常的文件管理工作中,我们经常会遇到同一个文件存在多个版本,或者需要验证备份文件与源文件是否一致,下面我们就来看看如何使用wxPython模... 目录引言项目背景与需求应用场景核心需求运行结果技术选型程序设计界面布局核心功能模块关键代码解析文件大

C++多线程开发环境配置方法

《C++多线程开发环境配置方法》文章详细介绍了如何在Windows上安装MinGW-w64和VSCode,并配置环境变量和编译任务,使用VSCode创建一个C++多线程测试项目,并通过配置tasks.... 目录下载安装 MinGW-w64下载安装VS code创建测试项目配置编译任务创建 tasks.js