介绍一下GateApp的启动流程,其实别的进程启动流程也是类似
rimServer.init
首先找到main函数
转到run_main看看内容
挑重点讲:
第一个红框里声明了rimServer对象
然后第二个红框给红框设定配置文件,以及跨服文件
最后一个红框对这个rimServer对象进行初始化
接下来先看看这个rimServer到底是什么东西
进入到engine源码部分:
直接看这个类的定义
查看init函数都做了一些什么事情
直接定位到函数实现
第一个#if 说明了 如果是在linux环境下,在不指定USED_ACE_TRB_PROACTOR的情况下需要执行的代码段,所以这一段内容可以暂时忽略掉
一步一步看执行的函数:
CTinyXml::initialize();
这里不展开说明,实际上是tinyXml的初始化,tinyxml 生成或解析XML非常好用
CProactor::instance();
在Windows下使用的是Proactor事件模型,进去看看有什么内容
这个Proactor对象保存了一个单例_instance 如果为NULL 那么new一个CProactor,然后返回这个Proactor对象,看看构造函数的内容:
上面的代码显示这个成员被初始化了,且这个初始化的类名为CACEProactorImpl,这个Proactor类有两个成员:
上面图片看看IProactorImpl是什么:
其实是一个抽象的接口类。那么可以猜到CACEProactorImpl可能是继承了这个接口类。再看看CACEProactorImpl类的声明:
果不其然,这个接口继承了IProactorImpl,并且自己写了父类的虚函数方法。看看这个类的构造函数都干了一些什么:
看来在windows平台下,啥也没做,只是在linux平台下初始化了逻辑。先不去管他,暂时只看windows平台下的处理
回到最初
对Proactor的两个成员变量_instance和变量_IProactorImpl进行一个初始化
设置日志的初始化
这段代码首先,它定义了一个 CXml 类型的对象。
接下来,它创建了一个 cdf::COptions 对象,并添加了几个选项。这些选项的名称分别为 "server-config"、"server-name"、"cell-channel"、"copy-channel" 和 "times"。这些选项都需要一个参数(即选项名称后需要提供一个参数值)。
然后,程序调用 options.parse(argc, argv) 来解析命令行参数和选项。这里的 argc 和 argv 是主函数的参数,它们包含了程序启动时传递给程序的所有命令行参数和选项。
接下来,程序检查是否设置了 "server-config" 选项。如果设置了,程序将使用 xml.loadFile 方法加载 options.optArg("server-config").c_str() 所指定的 XML 文件。否则,程序将检查是否设置了 _configFile 变量,如果没有设置,则程序将加载默认的文件 "engine_config.xml"。否则,程序将加载 _configFile 变量指定的文件。解析命令行参数和选项,并根据指定的选项加载一个 XML 文件。
加载完xml文件之后,读取xml对应的配置,对rimServer的成员变量进行赋值
_mqThreads :指定线程数量,如果没配置就默认为2个 先不去纠结这是啥,后续再看
_proactorThreads :同上,如果没有配置,就默认为4个
_proactorWaitTime:类似一个等待时间的东西,没设置就默认100
其中rimConfig是一个配置单例类
声明了一些参数,这里看个大概就行
xml的文件里也包含了这些值
接下来就是处理跨服文件
上述代码根据 _crossFile 变量指定的路径加载一个名为 "crossdomain.xml" 的文件。
首先,程序定义了一个 std::ifstream 对象 ifs,这是一个用于从文件中读取数据的输入流对象。
接下来,程序检查 _crossFile 变量是否为空。如果为空,程序将使用 CRMIConfig::instance()->getPath() 方法获取路径并添加文件名 "crossdomain.xml" 来打开文件。否则,程序将使用 _crossFile 变量指定的路径打开文件。
然后,程序检查是否成功打开了文件。如果成功打开了文件,程序将从文件中读取最多 sizeof(buf) 个字节的数据到 buf 中。然后,程序使用 std::string 构造函数将 buf 中的数据转换为一个字符串对象,并将其传递给 CAs3Protocol::setCrossdomain 方法,该方法将字符串保存为一个静态变量。最后,程序使用 CDF_LOG_TRACE 方法记录日志,将读取到的字符串打印出来。
总的来说,这段代码的作用是根据指定的路径加载一个名为 "crossdomain.xml" 的文件,并将其内容保存为一个字符串对象,以便其他部分的程序可以使用。同时,程序还记录了读取到的内容。
其中CAs3Protocol::setCrossdomain 就是对这个类的成员进行赋值,暂时可以不需要知道是干嘛的
这段初始化的核心内容应该就是这段代码了
这段代码的作用是根据 CRMIConfig::instance()->isSingleThread() 的值来创建一个 cdf::CReactor 实例,用于事件驱动程序的反应器模型。
如果 CRMIConfig::instance()->isSingleThread() 的值为真,则程序会使用 USED_ACE_PROACTOR 宏定义编译时选择的 proactor 库,创建一个 cdf::CAceTimerReactorImpl 实例作为反应器模型的实现,并将其包装在 cdf::CReactor 对象中。在创建 cdf::CAceTimerReactorImpl 实例时,程序指定了一个超时等待时间 _proactorWaitTime,一个指向 NULL 的回调函数指针和一个消息队列 cde::CBigMessageQueue::instance()。
否则,如果 CRMIConfig::instance()->isSingleThread() 的值为假,则程序会创建一个不带参数的 cdf::CTimerReactorImpl 实例作为反应器模型的实现,并将其包装在 cdf::CReactor 对象中。
总的来说,这段代码的作用是创建一个事件驱动的反应器模型,并选择合适的反应器实现。这个反应器模型用于处理程序中的异步事件,例如网络 I/O 和定时器超时等。