4、临时设备类型消息事件
临时设备类型的默认消息事件在khala框架中由TempNodeType类实现。目前默认实现了login、devTpye、isLogin三个消息事件,这些消息事件无需设备进行登录操作,任何连接都可以获得该类型的消息响应。其中login涉及到登录生命周期管理,为保留事件,无法对其进行重写操作。其他消息事件都可以由用户根据实际业务需求进行重写,或添加新的临时设备类型消息事件。
1、重写临时设备类型消息
我们可以通过重写Khala默认实现的临时设备类型消息来满足实际需求,下面以重写devTpye为例进行说明:
devType消息事件是指获取当前连接的设备类型,如果为未登录设备则为temp_type,如果为已登录设备则为login_type,在已登录设备基础上还可以扩展更加具体的设备类型。在客户端测试中,在连接未登录状态下,也能获取devTpye、isLogin请求事件的响应。
我们首先创建一个新的名叫MyTempNodeType的类,该类继承于TempNodeType类,并在该类中重写onDevTypeMsg这个方法。在新方法中,我们在send连接具体设备类型的同时,加上"this is my devType"这句,用于区分原devType的实现。
class MyTempNodeType: public khala::TempNodeType { public: MyTempNodeType(); virtual ~MyTempNodeType(); //重写TempNodeType类的devType响应事件 virtual bool onDevTypeMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg, khala::Timestamp time) { std::string devType = infoNodePtr->getNodeType(); infoNodePtr->send("this is my devType:" + devType); return true; } };
同时在main函数中,我们通过nodeServer.setTempNodeTypeInstance(&myTempNodeType)向系统注册我们新创建的MyTempNodeType类。
int main() { InetAddress listenAddr(USER_PORT); NodeServer nodeServer(listenAddr); //创建MyTempNodeType对象 MyTempNodeType myTempNodeType; //将该对象注册为新的TempNodeType nodeServer.setTempNodeType(&myTempNodeType); nodeServer.start(USER_SERVER_THREAD_NUM); return 0; }
只需以上两个简单的步骤,我们就很方便的完成了对devTpye的临时设备类型消息响应事件的重写。此时我们可以运行新的服务端程序,同时启动客户端进行测试:
2、创建新的临时设备类型消息
显然默认的两个临时设备类型消息是无法满足我们对于服务端系统的要求的,khala框架同样提供了创建新的非登录消息响应事件的途径。下面通过创建一个获取当前系统时间的临时设备类型消息。
首先必须为这个事件设置一个消息类型,可以在./include/khala/ParseKey.h中添加TIME_TYPE。新添加的消息类型必须为唯一设置的字符串。
//this is default msg type #define LOGIN_TYPE "login" #define LOGOUT_TYPE "logout" #define DEV_TYPE "dev" #define IS_LOGIN_TYPE "isLogin" #define NODE_ID_TYPE "nodeId" //this is my msg type #define TIME_TYPE "time"
依旧基于之前创建的新类MyTempNodeType,我们在这个类中新建方法onTimeMsg,在该方法中,我们实现获取时间的消息响应事件。
class MyTempNodeType: public khala::TempNodeType { public: MyTempNodeType(); virtual ~MyTempNodeType();
//重写TempNodeType的devType响应事件 virtual bool onDevTypeMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg, khala::Timestamp time) { std::string devType = infoNodePtr->getNodeType(); infoNodePtr->send("this is my devType:" + devType); return true; }
//新建time响应事件 virtual bool onTimeMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg, khala::Timestamp time){ std::string timeStr = khala::Timestamp::now().toFormattedString(); infoNodePtr->send("curr time:" + timeStr); return true; }
//消息注册方法 virtual void setRegisterMsg(khala::RegisterHandler& handler){
//调用父类的setRegisterMsg方法 khala::TempNodeType::setRegisterMsg(handler);
//注册time响应事件 handler.setRegisterMsg(TIME_TYPE,boost::bind(&MyTempNodeType::onTimeMsg, this, _1, _2, _3)); } };
此时虽然我们实现了获取时间的新建方法onTimeMsg(),但是系统并不知道这个方法的存在,此时需要接着重写消息注册方法setRegisterMsg(),并在该方法中完成对新创建的onTimeMsg方法的注册。
在重写setRegisterMsg方法完成注册前,必须显示调用父类的setRegisterMsg方法,否则将会丢失父类注册的消息响应事件,即无法识别原TempNodeType类默认实现的login、devTpye、isLogin等消息事件。
最后同样在main函数中通过nodeServer.setTempNodeTypeInstance(&myTempNodeType)向系统注册我们新创建的MyTempNodeType类。
这时我们已经创建了新的临时设备类型消息事件time。我们运行新的服务端程序,同时启动添加了time事件的客户端程序(./example/testClient/HelloKhalaClient2.py)进行测试:
此时我们在未登录的情况下,通过time消息事件获得了系统时间。
同时我们注意到虽然我们重写了TempNodeType类,但此时原TempNodeType默认实现的isLogin消息事件依旧能够被我们请求响应。如果有兴趣的话,可以尝试重写setRegisterMsg方法时,不显示调用父类的setRegisterMsg()方法,会发生什么?
我们可以继续在登录后请求time消息事件,此时依旧能够获得系统时间。我们新创建的time消息事件是跟登录无关的,任何连接都可以请求此消息响应,符合我们之前对临时设备类型消息的定义。