本文主要是介绍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 三层重构原有的功能 - 头文件
三层结构重构原有功能
- 自定义消息类,继承UserData,添加一个成员变量szUserData
- 定义多个Role类继承Irole,重写ProcMsg函数,进行不同处理
- 定义protocol类,继承Iprotocol,重写四个函数,两个函数时原始
数据和用户数据之间的转换;另两个用来找消息处理对象和消息发
送对象。 - 定义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单例模式
- 原始数据和业务数据相互函数,开发者重写该函数,实现协议
- 获取处理角色对象函数,开发者应该重写该函数,用来指定当前产生的用户数据消
- 获取发送通道函数,开发者应该重写该函数,用来指定当前字节流应该由哪个通道对象发出
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 控制输入输出
- 写一个关闭输出的角色类,摘除输出通道或添加输出通道
- 在CmdMsg用户数据类中添加开关标志,是否是命令标志
- 在协议类中,根据输入字符串,设置开关标志和是否是命令的标志
- 在协议类分发消息时,判断是否是命令,是命令则发给关闭输出角 色类,否则发给回显角色类
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:按照三层结构模式重构代码功能-待续的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!