1、导出基类库
之前的服务框架是以可执行程序的方式实现的,现在需要导出lib库。
修改框架项目的CMakeLists.txt文件中的导出配置
#add_executable(SimpleService ${SRC_LIST})
add_library(ServiceBase STATIC ${SRC_LIST})
编译文件,得到libServiceBase.a,放到lib文件夹。
将相应的头文件导出到include文件夹。
2、创建一个新项目
新创建一个项目,起名为ChatService,用来实现聊天服务项目。
首先编写整个服务的入口main.cpp
#include "ChatService.h"
int main(){
ChatService svr;
svr.Start();
return 0;
}
入口是一个简单的main函数,包含ChatService.h头文件,函数主题创建了一个聊天服务,执行服务的Start() 方法,后面的工作就交给服务类了。
#pragma once
#include "NetService.h"
#include "RoomMgr.h"
class ClientUser;
class ChatService :
public CNetService
{
public:
ChatService();
public:
virtual CLinkUser* CreateUser(int nOrigin);
public:
virtual void OnTimeOut(time_t tNow);
public:
int OnCreateRoom(int64_t sesID, int& nRoomID);
int JoinRoom(int64_t sesID, int& nRoomID, ClientUser* pUser);
int OnSendRoomMsg(int64_t sesID, int nRoomID, std::string& msg);
int OnClientBreak(int64_t sesID);
private:
RoomMgr m_roomMgr;
};
extern ChatService* g_pService;
服务继承于基类NetService,并重写了两个基类函数CreateUser(int nOrigine)和OnTimeOut(time_t tNow)。
CreateUser函数根据数据来源,确认连接者身份,并生成对应的连接对象,在这里是ClientUser代表客户端连接对象。
CLinkUser* ChatService::CreateUser(int nOrigin)
{
switch(nOrigin)
{
case ORIGINE_CLIENT:
return new ClientUser();
}
return nullptr;
}
在程序开发中,尽量使用命名常量替代具体的数字,这有两个好处:1是代码容易阅读理解,2是多处使用的时候,如果需要修改,只需修改定义赋值的地方。此处标识客户端来源定义的变量是ORIGINE_CLIENT,其定义放在了ChatProtocol.h中
#pragma once
#include "Protocol.h"
const int ORIGINE_CLIENT = 1;
const int ORIGINE_CHATSVR = 2001;
当客户端发送消息到服务端时,服务端先根据客户端Header中的Origine属性,调用服务重写的CreateUser函数,得到对应的User对象。基类实现的具体流程参见 《第二章第二节 增加监听端口》一节的内容。
OnTimeOut函数提供了一个30秒的定时轮询,每隔30秒触发一次函数调用,用于服务常规的定时检测,ChatService中的实现为
void ChatService::OnTimeOut(time_t tNow)
{
m_roomMgr.Check();
}
另外,服务的构造函数中给一些变量进行赋值。首先给全局变量g_pService赋值,便于服务其他地方调用服务函数。m_nPort是继承自NetService的成员变量,赋值后服务将监听这个端口。
SetLogName函数设置了服务输出日志的文件名,如果不设置,默认输出到ServiceBase.log文件中。
#include "ChatService.h"
#include "ClientUser.h"
#include "Protocol.h"
#include <iostream>
#include "HYLog.h"
#include "HYFunc.h"
ChatService* g_pService = nullptr;
ChatService::ChatService()
{
g_pService = this;
m_nPort = 21100;
SetLogName("./ChatService.log");
}
以上便基于服务框架创建了一个新的服务,可以监听服务自定义的端口,输出日志到指定文件,每隔30秒定期执行一次函数回调。
下一节,我们介绍ClientUser的实现。