前面说过db模块,子模块的启动部分基本都差不多。所以我只介绍不同的地方。gate模块和db模块不同的地方是,gate即作为master的leafnode,同时自己也作为其它模块(net,game1,admin)的root,代码如下。
if rootport:
self.root =PBRoot("rootservice")
reactor.listenTCP(rootport, BilateralFactory(self.root))
GlobalObject().root = self.root
大家如果看过前面的章节会发现这段代码也很熟悉,对! 它就是master模块的__startRoot函数一样的功能。我们前面在PB章节也详细介绍过。
OK,gate启动代码算介绍完了(怎么感觉什么都没有说呢?),大家瞅一眼我在github上的代码就一目了然了。
下面介绍gate的游戏部分内容,即app目录下面的内容。
这部分代码和db对应部分的调用过程一模一样,我们直接运行到app/gateserver.py。
就一行代码,
initconfig.loadModule()
跟进去发现代码如下:(代码我改过)
def loadModule():
rservices.init()
lservices.init()
实际上gate的app部分工作只是注册root services和local services的命令。
前面我们强调过services,是非常重要的类,系统通过这个类来实现具体功能。一个模块可能有多个services。这里我们就碰到了这种情况。
gate模块有3个services,他们分别是:
1、与master通讯的leafNode的services,包括2条命令:stop和reload。
2、自己作为root的services,通过上面loadModule()里面的rservices.init()注册以下几个命令。代码在:app/gate/rootservice/rservices.py(见我github的目录结构)
def init():
addToRootService(forwarding)
addToRootService(pushObject)
addToRootService(opera_player)
addToRootService(netconnlost)
3、一个挂接在 GlobalObject().localservice 的services,这个services通过lservices.init()注册3条命令,如下:
addToLocalService(loginToServer_101)
addToLocalService(activeNewPlayer_102)
addToLocalService(roleLogin_103)
其中 services 1是leafnode的services,所以会被作为root的master调用。
services 2 是自己作为root的services,所以会被gate的leafnode(net,game1,admin等)调用。
而services 3并没有挂接到某个PB端(root,或者node),它是在services2的forwarding()函数中通过以下方式调用:
def forwarding(key,dynamicId,data):
"""
"""
if key inGlobalObject().localservice._targets:
returnGlobalObject().localservice.callTarget(key,dynamicId,data)
else:
xxxxxx xxxxx xxxx #其它代码逻辑
所以,实际上services3 可以看做services 2的一部分,只是实现上独立出来成为一个services而已。
我们前面PB章节已经说过firefly的分布式调用逻辑。这里补充一下。
net模块(后面会介绍)会receive客户端(cocos2dx)的数据包,解析出具体命令,然后通过PB的方式,把命令当成参数来远程调用gate的PBRoot的remote_callTarget()函数。
而这个remote_callTarget()会进一步调用自己的services,也就是上面提到的services 2来处理命令。
Forexample:
(在firefly源码目录下面有一个tool目录,里面有测试代码clienttest.py可以用来做测试,我们后面介绍net模块的时候尽量详细扒数据,这里只是简单说一下示意流程)
1、客户端登陆,会发送用户名密码的json串给net模块
2、net模块解析出命令为:101, 参数为{username:xxx,password:xxx};
3、net远程调用gate的remote_callTarget()函数。
4、remote_callTarget()调用PBRoot.services.callTarget,通过解析命令101取得对应的命令函数loginToServer_101()并执行。(这个解析命令过程,就是前面提到mapTarget和unMapTarget函数实现);
OK,数据流我们就简单提一下,帮助大家理解模块功能。后面在net,game1模块流程都介绍完毕以后,我们会专门用1,2个章节来仔细分析分析暗黑的数据格式和各种流程。如果有时间和精力,我们尝试反推一下策划,设计内容。
下面一章我们介绍net,再下一章介绍game1,admin就留给读者自己看吧。