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

前言

    本文使用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)
// 请求强制杀死当前app
MACHINE_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的虚函数,第二次定义了实现,如果是属于自身的就会回调,反之则不做处理*/

发布了54 篇原创文章 · 获赞 1 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u011255131/article/details/53470221
今日推荐