转行做游戏(2) Kbengine serverapp结构初步解析

来源:互联网 发布:java 预测算法 编辑:程序博客网 时间:2024/06/05 02:35

前言

    本文使用machine为例进行说明。为什么是的是Machine呢?这个还得从keb启动脚本说起。以start_server.bat为例start_server.bat一开始巴拉巴拉一大堆。然后启动的第一个app
start %KBE_BIN_PATH%/machine.exe --cid=1000 --gus=1
启动了machine。So..

正文

当然了我们也是从main函数开始

main 函数

...int KBENGINE_MAIN(int argc, char* argv[]){#if KBE_PLATFORM != PLATFORM_WIN32    rlimit rlimitData = { RLIM_INFINITY, RLIM_INFINITY };    setrlimit(RLIMIT_CORE, &rlimitData);#endif        ENGINE_COMPONENT_INFO& info = g_kbeSrvConfig.getKBMachine();    int ret = kbeMainT<Machine>(argc, argv, MACHINE_TYPE, info.externalPorts_min,         info.externalPorts_max, "", 0, info.internalInterface);    return ret; }...

KBENGINE_MAIN的定义

#if KBE_PLATFORM == PLATFORM_WIN32#define KBENGINE_MAIN                       \kbeMain(int argc, char* argv[]);            \int main(int argc, char* argv[])            \{                                           \    loadConfig();                           \    g_componentID = genUUID64();            \    parseMainCommandArgs(argc, argv);       \    char dumpname[MAX_BUF] = {0};           \    kbe_snprintf(dumpname, MAX_BUF, "%"PRAppID, g_componentID);\    KBEngine::exception::installCrashHandler(1, dumpname);     \    int retcode = -1;                       \    THREAD_TRY_EXECUTION;                   \    retcode = kbeMain(argc, argv);          \    THREAD_HANDLE_CRASH;                    \    return retcode;                         \}                                           \int kbeMain#else#define KBENGINE_MAIN                       \kbeMain(int argc, char* argv[]);            \int main(int argc, char* argv[])            \{                                           \    loadConfig();                           \    g_componentID = genUUID64();            \    parseMainCommandArgs(argc, argv);       \    return kbeMain(argc, argv);             \}                                           \int kbeMain#endif

KBENGINE_MAIN干了些啥

KBENGINE_MAIN让所有的app都做了3件事,
loadConfig();//载入配置信息,必须要说的事,这只是载入基本配置,如果是app特有的配置后续还会有g_componentID = genUUID64();//生成app进程的唯一标示parseMainCommandArgs(argc, argv);//解析Command参数,其实只有3种。 --cid=,--gus=还有--hide=

KBENGINE_MAIN定义的疑惑

在这里应该有两个疑惑:

Resmgr 重复初始化

在Machine中就存在某个全局变量导致Resmgr::getSingleton().initialize();在main之前就执行过一次。
奇怪的是initialize()原本是 有判断是否有过初始化的,但是被注释掉了。

Command --gus= 参数无意义

在genUUID64()中会根据g_genuuid_sections是否为有效值而使用两种不同的方式生成uuid。
but,令人惊讶是的g_genuuid_sections是Command中的--gus=。而Command的解析居然在genUUID64()之后。

QTMD,不管了,我们接着说表面的Main函数。

kbemain

这里使用了模板kbeMainT

kbeMainT 的构造函数

我已经把打印日志的代码去掉了,这样看上去会简洁那么一丢丢。。


template <class SERVER_APP>int kbeMainT(int argc, char * argv[], COMPONENT_TYPE componentType,              int32 extlisteningPort_min = -1, int32 extlisteningPort_max = -1, const char * extlisteningInterface = "",             int32 intlisteningPort = 0, const char * intlisteningInterface = ""){    setEvns();    startLeakDetection(componentType, g_componentID);    g_componentType = componentType;    DebugHelper::initialize(componentType);    KBEKey kbekey(Resmgr::getSingleton().matchPath("key/") + "kbengine_public.key",         Resmgr::getSingleton().matchPath("key/") + "kbengine_private.key");    Network::EventDispatcher dispatcher;    DebugHelper::getSingleton().pDispatcher(&dispatcher);    const ChannelCommon& channelCommon = g_kbeSrvConfig.channelCommon();    Network::g_SOMAXCONN = g_kbeSrvConfig.tcp_SOMAXCONN(g_componentType);    Network::NetworkInterface networkInterface(&dispatcher,         extlisteningPort_min, extlisteningPort_max, extlisteningInterface,         channelCommon.extReadBufferSize, channelCommon.extWriteBufferSize,        (intlisteningPort != -1) ? htons(intlisteningPort) : -1, intlisteningInterface,        channelCommon.intReadBufferSize, channelCommon.intWriteBufferSize);    DebugHelper::getSingleton().pNetworkInterface(&networkInterface);    g_kbeSrvConfig.updateInfos(true, componentType, g_componentID,             networkInterface.intaddr(), networkInterface.extaddr());    Components::getSingleton().initialize(&networkInterface, componentType, g_componentID);    SERVER_APP app(dispatcher, networkInterface, componentType, g_componentID);    Components::getSingleton().findLogger();    START_MSG(COMPONENT_NAME_EX(componentType), g_componentID);    if(!app.initialize())    {        Components::getSingleton().finalise();        app.finalise();        // 如果还有日志未同步完成, 这里会继续同步完成才结束        DebugHelper::getSingleton().finalise();#if KBE_PLATFORM == PLATFORM_WIN32        // 等待几秒,让用户能够在窗口上看到信息        Beep(587, 500);        KBEngine::sleep(5000);#endif        return -1;    }    int ret = app.run();    Components::getSingleton().finalise();    app.finalise();    // 如果还有日志未同步完成, 这里会继续同步完成才结束    DebugHelper::getSingleton().finalise();    return ret;}

我们用广度优先的方式解读代码。
setEvns();//设置了一些环境变量startLeakDetection(componentType, g_componentID);//在machine中啥也没干。其他app中还不知道,这个暂不细究。DebugHelper::initialize(componentType);//跟了一下,好深~~不过,就是初始化一下日志什么的,先不深究,啦啦啦啦~~好多不深究。恩,我们是为了把精力放到更重要的地方,毕竟学海无涯而吾生有涯~~~KBEKey kbekey(Resmgr::getSingleton().matchPath("key/") + "kbengine_public.key", Resmgr::getSingleton().matchPath("key/") + "kbengine_private.key");//载入了一下公私key,还做了下对比,标示了下kbekey'是否有效Network::EventDispatcher dispatcher;//一个事件处理器,这个玩意会对event的增加,减少,执行进行处理,当然,它本身没有实现执行,只是调用DebugHelper::getSingleton().pDispatcher(&dispatcher);//设置了下处理器,并且启动的DebugHelper的timer//巴拉巴拉 各种初始化,包裹network的参数,srcConfig的各种参数const ChannelCommon& channelCommon = g_kbeSrvConfig.channelCommon();Network::g_SOMAXCONN = g_kbeSrvConfig.tcp_SOMAXCONN(g_componentType);Network::NetworkInterface networkInterface(&dispatcher, extlisteningPort_min, extlisteningPort_max, extlisteningInterface, channelCommon.extReadBufferSize, channelCommon.extWriteBufferSize,(intlisteningPort != -1) ? htons(intlisteningPort) : -1, intlisteningInterface,channelCommon.intReadBufferSize, channelCommon.intWriteBufferSize);DebugHelper::getSingleton().pNetworkInterface(&networkInterface);g_kbeSrvConfig.updateInfos(true, componentType, g_componentID, networkInterface.intaddr(), networkInterface.extaddr());Components::getSingleton().initialize(&networkInterface, componentType, g_componentID);//初始化了一下app需要查找的app。当然了,Machine不需要任何app

下面就是重点了


SERVER_APP app(dispatcher, networkInterface, componentType, g_componentID);Components::getSingleton().findLogger();//查找logger,当然了 Machine 又不需要if(!app.initialize())//初始化app各种东西,绝对的重要。。欲知详情,请听下回分解,还在本章哦~~~~{...//初始化失败了当然就是滚蛋了,有什么好说的}int ret = app.run();// app的主循环了,出来就已经gg了,//后面的暂时不管了,反正已经gg了,不重要了哈哈哈

ServerApp::initialize()

bool ServerApp::initialize(){    if(!initThreadPool())return false;//初始化线程池    if(!installSignals())return false;//注册信号    if(!loadConfig())return false;//载入特有的配置,通用配置已经在开始前就载入了    if(!initializeBegin())return false;//初始化前的准备    if(!inInitialize())return false;//初始化    bool ret = initializeEnd();//初始化后续处理#ifdef ENABLE_WATCHERS    return ret && initializeWatcher();#else    return ret;#endif}
在Machine中并没有其他的配置需要载入。

1.initializeBegin()

Machine初始化了NetWork,
分别对epBroadcast_,ep_,epLocal_三个监听做了初始化。监听的端口分别是20086,20087,20088端口,实际使用还未可知。后续再看。
epBroadcast_.socket(SOCK_DGRAM);
ep_.socket(SOCK_DGRAM);
epLocal_.socket(SOCK_DGRAM); 

2.inInitialize()

在Machine中并没有做什么特有的初始化动作

3.initializeEnd()

在Machine中因为并不需要依赖其他app所以也没做什么

bool Machine::run()

接下来就是run()了
bool Machine::run(){    bool ret = true;    while(!this->dispatcher().hasBreakProcessing())//这句话比较简单,就是检测下app是否该结束了    {        threadPool_.onMainThreadTick();//这个对finiTaskList_列表做了处理,把准备好,可以开始处理的放到worker中,处理玩的删除,还未准备好的放回原队        this->dispatcher().processOnce(false);//处理了一下主线程中的事务        networkInterface().processChannels(&MachineInterface::messageHandlers);//获取Network中的任务        KBEngine::sleep(100);    };    return ret;}

到现在,Machine中的逻辑基本清楚了。
各种初始化之后,分为主线程和worker线程两个部分处理事务。
主线程是处理network的事务,显然是不可以被阻塞的,那么有一些可能会阻塞的任务就会交给worker线程。
处理完之后还是回发给network。

ServerApp的Message定义方式

Machine会处理的Message

这个可以在machine_interface.h 中可以查看到
// 其他组件向app广播自己的接口地址MACHINE_MESSAGE_DECLARE_ARGS25(onBroadcastInterface,            NETWORK_VARIABLE_MESSAGE,                                int32,                          uid,                                 std::string,                    username,                                COMPONENT_TYPE,                 componentType,                                 COMPONENT_ID,                   componentID,                                 COMPONENT_ID,                   componentIDEx,                                 COMPONENT_ORDER,                globalorderid,                                 COMPONENT_ORDER,                grouporderid,                                 COMPONENT_GUS,                  gus,                                uint32,                         intaddr,                                 uint16,                         intport,                                uint32,                         extaddr,                                 uint16,                         extport,                                std::string,                    extaddrEx,                                uint32,                         pid,                                float,                          cpu,                                 float,                          mem,                                 uint32,                         usedmem,                                int8,                           state,                                uint32,                         machineID,                                 uint64,                         extradata,                                uint64,                         extradata1,                                uint64,                         extradata2,                                uint64,                         extradata3,                                uint32,                         backRecvAddr,                                uint16,                         backRecvPort)// 其他组件向app请求获取某个组件类别的地址    MACHINE_MESSAGE_DECLARE_ARGS7(onFindInterfaceAddr, NETWORK_VARIABLE_MESSAGE,                                int32, uid,                                std::string, username,                                COMPONENT_TYPE, componentType,                                COMPONENT_ID, componentID,                                COMPONENT_TYPE, findComponentType,                                uint32, addr,                                uint16, finderRecvPort)// 查询所有接口信息MACHINE_MESSAGE_DECLARE_ARGS3(onQueryAllInterfaceInfos,         NETWORK_VARIABLE_MESSAGE,                                int32,                          uid,                                 std::string,                    username,                                uint16,                         finderRecvPort)// 查询所有machine进程MACHINE_MESSAGE_DECLARE_ARGS3(onQueryMachines,                  NETWORK_VARIABLE_MESSAGE,                                int32,                          uid,                                 std::string,                    username,                                uint16,                         finderRecvPort)// 某app主动请求look。MACHINE_MESSAGE_DECLARE_ARGS0(lookApp,                          NETWORK_FIXED_MESSAGE)// 某个app请求查看该app负载状态。MACHINE_MESSAGE_DECLARE_ARGS0(queryLoad,                        NETWORK_FIXED_MESSAGE)// 启动服务器MACHINE_MESSAGE_DECLARE_STREAM(startserver,                     NETWORK_VARIABLE_MESSAGE)// 关闭服务器MACHINE_MESSAGE_DECLARE_STREAM(stopserver,                      NETWORK_VARIABLE_MESSAGE)// 关闭服务器MACHINE_MESSAGE_DECLARE_STREAM(killserver,                      NETWORK_VARIABLE_MESSAGE)// 请求强制杀死当前appMACHINE_MESSAGE_DECLARE_STREAM(reqKillServer,                   NETWORK_VARIABLE_MESSAGE)

Message定义展开

我们以
MACHINE_MESSAGE_DECLARE_ARGS7(onFindInterfaceAddr, NETWORK_VARIABLE_MESSAGE,    int32, uid,    std::string, username,    COMPONENT_TYPE, componentType,    COMPONENT_ID, componentID,    COMPONENT_TYPE, findComponentType,    uint32, addr,    uint16, finderRecvPort)


为例进行扩展,打开之后的代码为
class onFindInterfaceAddrMachineMessagehandler7 : public Network::MessageHandler{public:    void handle(Network::Channel* pChannel,        KBEngine::MemoryStream& s)     {        int32 uid;                                                        s >> uid;                                                                std::string username;                                                        s >> username;                                                                COMPONENT_TYPE componentType;                                                        s >> componentType;                                                                COMPONENT_ID componentID;                                                       s >> componentID;                                                                COMPONENT_TYPE findComponentType;                                                        s >> findComponentType;                                                                uint32 addr;                                                       s >> addr;                                                                uint16 finderRecvPort;                                                       s >> finderRecvPort;                                                                KBEngine::Machine::getSingleton().NAME(pChannel,                                                        uid, username, componentType,                                             componentID, findComponentType, addr,                                            finderRecvPort);                                     }};extern const onFindInterfaceAddrMachineMessagehandler7& onFindInterfaceAddr;class onFindInterfaceAddrArgs7 : public Network::MessageArgs                    {                                                                public:                                                                int32 uid;    std::string username;    COMPONENT_TYPE componentType;    COMPONENT_ID componentID;    COMPONENT_TYPE findComponentType;    uint32 addr;    uint16 finderRecvPort;public:                                                                onFindInterfaceAddrArgs7():Network::MessageArgs()                            {                                                                    strArgsTypes.push_back("int32");        strArgsTypes.push_back("std::string");                                strArgsTypes.push_back("COMPONENT_TYPE");        strArgsTypes.push_back("COMPONENT_ID");                                strArgsTypes.push_back("COMPONENT_TYPE");                                strArgsTypes.push_back("uint32");                                strArgsTypes.push_back("uint16");                            }                                                                onFindInterfaceAddrArgs7(    int32 init_uid,    std::string init_username,                                        COMPONENT_TYPE init_componentType,                                        COMPONENT_ID init_componentID,                                        COMPONENT_TYPE init_findComponentType,                                        uint32 init_addr,                                        uint16 init_finderRecvPort):                                    Network::MessageArgs(),        uid(init_uid),                                        username(init_username),                                        componentType(init_componentType),                                        componentID(init_componentID),        findComponentType(init_findComponentType),        addr(init_addr),        finderRecvPort(init_finderRecvPort)    {                                                                    strArgsTypes.push_back("int32");        strArgsTypes.push_back("std::string");        strArgsTypes.push_back("COMPONENT_TYPE");        strArgsTypes.push_back("COMPONENT_ID");        strArgsTypes.push_back("COMPONENT_TYPE");        strArgsTypes.push_back("uint32");        strArgsTypes.push_back("uint16");    }                                                                ~onFindInterfaceAddrArgs7(){}                                                                                                                static void staticAddToBundle(Network::Bundle& s,                    int32 init_uid,        std::string init_username,        COMPONENT_TYPE init_componentType,        COMPONENT_ID init_componentID,        COMPONENT_TYPE init_findComponentType,        uint32 init_addr,        uint16 init_finderRecvPort)    {                                                                    s << init_uid;        s << init_username;        s << init_componentType;        s << init_componentID;        s << init_findComponentType;        s << init_addr;        s << init_finderRecvPort;    }                                                                static void staticAddToStream(MemoryStream& s,                        int32 init_uid,        std::string init_username,        COMPONENT_TYPE init_componentType,        COMPONENT_ID init_componentID,        COMPONENT_TYPE init_findComponentType,        uint32 init_addr,        uint16 init_finderRecvPort)    {                                                                    s << init_uid;        s << init_username;        s << init_componentType;        s << init_componentID;        s << init_findComponentType;        s << init_addr;        s << init_finderRecvPort;    }                                                                virtual int32 dataSize(void)                                    {                                                                    return    sizeof(int32) +                sizeof(std::string) +                sizeof(COMPONENT_TYPE) +                sizeof(COMPONENT_ID) +                sizeof(COMPONENT_TYPE) +                sizeof(uint32) +                sizeof(uint16);    }                                                                virtual void addToStream(MemoryStream& s)                        {                                                                    s << uid;        s << username;        s << componentType;        s << componentID;        s << findComponentType;        s << addr;        s << finderRecvPort;    }                                                                virtual void createFromStream(MemoryStream& s)                    {                                                                    s >> uid;        s >> username;        s >> componentType;        s >> componentID;        s >> findComponentType;        s >> addr;        s >> finderRecvPort;    }                                                            };


这个是我手工展开的,所以很能有cp错误什么的。。看下就好了。不知道有什么工具能把宏展开~~~~(说不得哪天闲的蛋疼,我就自己写一个小工具,报着亿万分之一的可能性来期待吧,哈哈哈)
看上去还是很规则的。基本就是定义了下Machine的Message的生成什么的。然后在handle方法中调用了Machine的对应接口。
值得一提的是我在使用vs2015进行跟进的时候。得到进入的到handle是一个没有实现的虚函数。。。折腾了好久,最后查询了下
MACHINE_MESSAGE_HANDLER_STREAM
的所有定义,然后发现了我想要的结果,接着做了下小小的测试。
MACHINE_MESSAGE_HANDLER_STREAM确实是使用的这个展开的定义。
看了下整体结构,应该是只有app自身在定义属于自身的Message的时候才会产生回调。其他时候则只是普通的消息。
/*这里搞错了,这个宏是会被展开两次的,第一次定义了class的虚函数,第二次定义了实现,如果是属于自身的就会回调,反之则不做处理*/

0 0