生活随笔
收集整理的這篇文章主要介紹了
python firefly 游戏引擎 教程(二) 程序入口
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
第一章我們講了程序的基本啟動(dòng)流程,這里面涉及到了各種節(jié)點(diǎn)信息,master,net,gate,game…,當(dāng)然,無論他叫什么名字,歸根結(jié)底他都是一個(gè)節(jié)點(diǎn)。就好比爺爺爸爸兒子,就像是父父節(jié)點(diǎn),父節(jié)點(diǎn),子節(jié)點(diǎn),不管在家里地位如何,他終究是人。那么是如何實(shí)現(xiàn)這個(gè)分布式節(jié)點(diǎn)的呢,我們這章進(jìn)入firefly源碼內(nèi)一探究竟
節(jié)點(diǎn)相關(guān)的文件都存放在distributed,也就是分布式模塊當(dāng)中
distributed模塊說明 該模塊主要封裝了關(guān)于節(jié)點(diǎn)的所有方法以及類 distributed模塊結(jié)構(gòu)解析
PBRoot,root節(jié)點(diǎn)對(duì)象(所有擁有child節(jié)點(diǎn)的都是root節(jié)點(diǎn),root節(jié)點(diǎn)本身可以有root節(jié)點(diǎn),好比爺爺是root節(jié)點(diǎn),爸爸是root節(jié)點(diǎn),因?yàn)樗麄兌加袃鹤?#xff0c;但是兒子就只能是child節(jié)點(diǎn))
ChildsManager,子節(jié)點(diǎn)管理基類 Child 對(duì)象對(duì)應(yīng)的是連接到本服務(wù)進(jìn)程的某個(gè)服務(wù)進(jìn)程對(duì)象。稱為子節(jié)點(diǎn)對(duì)象
RemoteObject遠(yuǎn)程調(diào)用對(duì)象,所有child對(duì)象都是一個(gè)遠(yuǎn)程調(diào)用對(duì)象,遠(yuǎn)程調(diào)用對(duì)象封裝了一個(gè)child對(duì)象和child對(duì)象的遠(yuǎn)程代理通道(用于反向調(diào)用),以及service對(duì)象(用于提供遠(yuǎn)程調(diào)用的方法,在下面你會(huì)看到很多他的身影,你可先不用管他是什么,只需要知道他能提供被調(diào)用的方法就可以了,因?yàn)樵谙乱徽?#xff0c;我們會(huì)詳細(xì)描述service)
分布式模塊的文件結(jié)構(gòu)如下 模塊結(jié)構(gòu)如下:
文件結(jié)構(gòu):
- distributed
- __init__
. py
- child
. py
- manager
. py
- node
. py
- reference
. py
- root
. py
'''
Created on 2013-8-14@author: lan (www.9miao.com)
'''
class Child ( object ) : '''子節(jié)點(diǎn)對(duì)象''' def __init__ ( self
, cid
, name
) : '''初始化子節(jié)點(diǎn)對(duì)象''' self
. _id
= cidself
. _name
= nameself
. _transport
= None def getName ( self
) : '''獲取子節(jié)點(diǎn)的名稱''' return self
. _name
def setTransport ( self
, transport
) : '''設(shè)置子節(jié)點(diǎn)的通道''' self
. _transport
= transport
def callbackChild ( self
, * args
, ** kw
) : '''回調(diào)子節(jié)點(diǎn)的接口return a Defered Object (recvdata)''' recvdata
= self
. _transport
. callRemote
( 'callChild' , * args
, ** kw
) return recvdata
'''
Created on 2013-8-14@author: lan (www.9miao.com)
'''
from twisted
. python
import log
from zope
. interface
import Interface
from zope
. interface
import implements
class _ChildsManager ( Interface
) : '''節(jié)點(diǎn)管理器接口''' def __init__ ( self
) : '''初始化接口''' def getChildById ( self
, childId
) : '''根據(jù)節(jié)點(diǎn)id獲取節(jié)點(diǎn)實(shí)例''' def getChildByName ( self
, childname
) : '''根據(jù)節(jié)點(diǎn)的名稱獲取節(jié)點(diǎn)實(shí)例''' def addChild ( self
, child
) : '''添加一個(gè)child節(jié)點(diǎn)@param child: Child object''' def dropChild ( self
, * arg
, ** kw
) : '''刪除一個(gè)節(jié)點(diǎn)''' def callChild ( self
, * args
, ** kw
) : '''調(diào)用子節(jié)點(diǎn)的接口''' def callChildByName ( self
, * args
, ** kw
) : '''調(diào)用子節(jié)點(diǎn)的接口@param childname: str 子節(jié)點(diǎn)的名稱''' def dropChildByID ( self
, childId
) : '''刪除一個(gè)child 節(jié)點(diǎn)@param childId: Child ID ''' def dropChildSessionId ( self
, session_id
) : """根據(jù)session_id刪除child節(jié)點(diǎn)""" @implementer
( _ChildsManager
)
class ChildsManager ( object ) :
'''
子節(jié)點(diǎn)管理器
因?yàn)檠b飾器implementer
用戶必須得完成_ChildsManager的所有方法
''' def __init__ ( self
) : '''初始化子節(jié)點(diǎn)管理器''' self
. _childs
= { } def getChildById ( self
, childId
) : '''根據(jù)節(jié)點(diǎn)的ID獲取節(jié)點(diǎn)實(shí)例''' return self
. _childs
. get
( childId
) def getChildByName ( self
, childname
) : '''根據(jù)節(jié)點(diǎn)的名稱獲取節(jié)點(diǎn)實(shí)例遍歷子節(jié)點(diǎn)從中提取節(jié)點(diǎn)名稱為childname的節(jié)點(diǎn)''' for key
, child
in self
. _childs
. items
( ) : if child
. getName
( ) == childname
: return self
. _childs
[ key
] return None def addChild ( self
, child
) : '''添加一個(gè)child節(jié)點(diǎn)@param child: Child object''' key
= child
. _id
if self
. _childs
. has_key
( key
) : raise "child node %s exists" % keyself
. _childs
[ key
] = child
def dropChild ( self
, child
) : '''刪除一個(gè)child 節(jié)點(diǎn)@param child: Child Object ''' key
= child
. _id
try : del self
. _childs
[ key
] except Exception
, e
: log
. msg
( str ( e
) ) def dropChildByID ( self
, childId
) : '''通過ID刪除一個(gè)child 節(jié)點(diǎn)@param childId: Child ID ''' try : del self
. _childs
[ childId
] except Exception
, e
: log
. msg
( str ( e
) ) def callChild ( self
, childId
, * args
, ** kw
) : '''調(diào)用子節(jié)點(diǎn)的接口@param childId: int 子節(jié)點(diǎn)的id''' child
= self
. _childs
. get
( childId
, None ) if not child
: log
. err
( "child %s doesn't exists" % childId
) return return child
. callbackChild
( * args
, ** kw
) def callChildByName ( self
, childname
, * args
, ** kw
) : '''通過節(jié)點(diǎn)名稱調(diào)用子節(jié)點(diǎn)的接口@param childname: str 子節(jié)點(diǎn)的名稱''' child
= self
. getChildByName
( childname
) if not child
: log
. err
( "child %s doesn't exists" % childname
) return return child
. callbackChild
( * args
, ** kw
) def getChildBYSessionId ( self
, session_id
) : """根據(jù)sessionID獲取child節(jié)點(diǎn)信息""" for child
in self
. _childs
. values
( ) : if child
. _transport
. broker
. transport
. sessionno
== session_id
: return child
return None
node.py 介紹了那么多關(guān)于子節(jié)點(diǎn)的內(nèi)容, 下面我們正式開始揭開子節(jié)點(diǎn)的面紗。
'''
Created on 2013-8-14@author: lan (www.9miao.com)
'''
from twisted
. spread
import pb
from twisted
. internet
import reactor
reactor
= reactor
from reference
import ProxyReference
def callRemote ( obj
, funcName
, * args
, ** kw
) : '''遠(yuǎn)程調(diào)用(這里只是作為一個(gè)調(diào)用子節(jié)點(diǎn)的方法存在)@param obj 子節(jié)點(diǎn)對(duì)象,也就是RemoteObject@param funcName: str 遠(yuǎn)程方法名稱''' return obj
. callRemote
( funcName
, * args
, ** kw
) class RemoteObject ( object ) : '''遠(yuǎn)程調(diào)用對(duì)象也就是真正的子節(jié)點(diǎn)''' def __init__ ( self
, name
) : '''初始化遠(yuǎn)程調(diào)用對(duì)象@param port: int 遠(yuǎn)程分布服的端口號(hào)@param rootaddr: 根節(jié)點(diǎn)服務(wù)器地址''' self
. _name
= name self
. _factory
= pb
. PBClientFactory
( ) self
. _reference
= ProxyReference
( ) self
. _addr
= None def setName ( self
, name
) : '''設(shè)置節(jié)點(diǎn)的名稱''' self
. _name
= name
def getName ( self
) : '''獲取節(jié)點(diǎn)的名稱''' return self
. _name
def connect ( self
, addr
) : '''初始化遠(yuǎn)程調(diào)用對(duì)象''' self
. _addr
= addr reactor
. connectTCP
( addr
[ 0 ] , addr
[ 1 ] , self
. _factory
) self
. takeProxy
( ) def reconnect ( self
) : '''重新連接''' self
. connect
( self
. _addr
) def addServiceChannel ( self
, service
) : '''設(shè)置引用對(duì)象''' self
. _reference
. addService
( service
) def takeProxy ( self
) : '''向遠(yuǎn)程服務(wù)端發(fā)送代理通道對(duì)象twisted的雙向透明代理規(guī)定的步驟1.向服務(wù)器請(qǐng)求root對(duì)象2.通過root對(duì)象向服務(wù)器發(fā)送自身的ProxyReference(代理通道)3.雙向連接完成''' deferedRemote
= self
. _factory
. getRootObject
( ) deferedRemote
. addCallback
( callRemote
, 'takeProxy' , self
. _name
, self
. _reference
) def callRemote ( self
, commandId
, * args
, ** kw
) : '''這里就是正式的遠(yuǎn)程調(diào)用函數(shù)了,子節(jié)點(diǎn)調(diào)用父節(jié)點(diǎn)的方法和建立雙向透明代理類似,調(diào)用的步驟為:1.獲取遠(yuǎn)程root對(duì)象2.通過root對(duì)象調(diào)用服務(wù)器函數(shù)@param callRemote 這里調(diào)用的就是該文件頂部的那個(gè)同名函數(shù)由于 addCallback會(huì)將 異步獲取的 對(duì)象傳入Callback 中也就是傳入 callRemote 這個(gè)函數(shù)內(nèi),所以最終實(shí)現(xiàn)的效果是 :self._factory.getRootObject().callRemote('callTarget', ,commandId,*args,**kw)@param callTarget 這是firefly定義的遠(yuǎn)程調(diào)用函數(shù)函數(shù)名稱@param commandId 遠(yuǎn)程對(duì)象會(huì)根據(jù) commandId 來最終絕對(duì)執(zhí)行什么操作''' deferedRemote
= self
. _factory
. getRootObject
( ) return deferedRemote
. addCallback
( callRemote
, 'callTarget' , commandId
, * args
, ** kw
)
'''
Created on 2013-8-14@author: lan (www.9miao.com)
'''
from twisted
. spread
import pb
from firefly
. utils
. services
import Service
class ProxyReference ( pb
. Referenceable
) : '''代理通道''' def __init__ ( self
) : '''初始化''' self
. _service
= Service
( 'proxy' ) def addService ( self
, service
) : '''添加一條服務(wù)通道''' self
. _service
= service
def remote_callChild ( self
, command
, * arg
, ** kw
) : '''代理發(fā)送數(shù)據(jù)''' return self
. _service
. callTarget
( command
, * arg
, ** kw
)
父節(jié)點(diǎn)對(duì)象 -root.py 最后我們來看看分布式節(jié)點(diǎn)的中心root節(jié)點(diǎn),當(dāng)然這里的所謂中心并不代表只有一個(gè)root節(jié)點(diǎn),比如暗黑世界里,直觀的你就能發(fā)現(xiàn)master和gate都是root節(jié)點(diǎn),對(duì)于master而言,gate又是他的子節(jié)點(diǎn)。同理,game同樣可以作為一個(gè)root節(jié)點(diǎn)(當(dāng)然在暗黑世界里,game是一個(gè)child節(jié)點(diǎn)),然后分裂出game1,game2,game3…,但同時(shí),又是gate的子節(jié)點(diǎn),這其中并不矛盾。
'''
Created on 2013-8-14
分布式根節(jié)點(diǎn)
@author: lan (www.9miao.com)
'''
from twisted
. python
import log
from twisted
. spread
import pb
from manager
import ChildsManager
from child
import Child
class BilateralBroker ( pb
. Broker
) : '''''' def connectionLost ( self
, reason
) : '''這里重寫了pb.broker的連接丟失方法,用于子連接丟失后將子節(jié)點(diǎn)從根節(jié)點(diǎn)中移除''' clientID
= self
. transport
. sessionno log
. msg
( "node [%d] lose" % clientID
) self
. factory
. root
. dropChildSessionId
( clientID
) pb
. Broker
. connectionLost
( self
, reason
) class BilateralFactory ( pb
. PBServerFactory
) : '''重寫 PBServerFactory 類,目的只是為了重寫pb.Broker的connectionLost方法,而重寫connectionLost方法只是為了將子節(jié)點(diǎn)斷開后,從根節(jié)點(diǎn)中將對(duì)象刪除,保持根節(jié)點(diǎn)對(duì)于子節(jié)點(diǎn)信息存儲(chǔ)的準(zhǔn)確性''' protocol
= BilateralBroker
class PBRoot ( pb
. Root
) : '''繼承PB 協(xié)議的root節(jié)點(diǎn)''' def __init__ ( self
, dnsmanager
= ChildsManager
( ) ) : '''初始化根節(jié)點(diǎn)''' self
. service
= None self
. childsmanager
= dnsmanager
def addServiceChannel ( self
, service
) : '''添加服務(wù)通道@param service: Service Object(In bilateral.services)''' self
. service
= service
def doChildConnect ( self
, name
, transport
) : """當(dāng)node節(jié)點(diǎn)連接時(shí)的處理""" pass def dropChild ( self
, * args
, ** kw
) : '''刪除子節(jié)點(diǎn)記錄''' self
. childsmanager
. dropChild
( * args
, ** kw
) def dropChildByID ( self
, childId
) : '''刪除子節(jié)點(diǎn)記錄''' self
. doChildLostConnect
( childId
) self
. childsmanager
. dropChildByID
( childId
) def dropChildSessionId ( self
, session_id
) : '''刪除子節(jié)點(diǎn)記錄''' child
= self
. childsmanager
. getChildBYSessionId
( session_id
) if not child
: return child_id
= child
. _idself
. doChildLostConnect
( child_id
) self
. childsmanager
. dropChildByID
( child_id
) def doChildLostConnect ( self
, childId
) : """當(dāng)node節(jié)點(diǎn)連接時(shí)的處理""" pass def callChild ( self
, key
, * args
, ** kw
) : '''調(diào)用子節(jié)點(diǎn)的接口@param childId: int 子節(jié)點(diǎn)的idreturn Defered Object''' return self
. childsmanager
. callChild
( key
, * args
, ** kw
) def callChildByName ( self
, childname
, * args
, ** kw
) : '''調(diào)用子節(jié)點(diǎn)的接口@param childId: int 子節(jié)點(diǎn)的idreturn Defered Object''' return self
. childsmanager
. callChildByName
( childname
, * args
, ** kw
) def remote_takeProxy ( self
, name
, transport
) : '''設(shè)置代理通道@param addr: (hostname,port)hostname 根節(jié)點(diǎn)的主機(jī)名,根節(jié)點(diǎn)的端口''' log
. msg
( 'node [%s] takeProxy ready' % name
) child
= Child
( name
, name
) self
. childsmanager
. addChild
( child
) child
. setTransport
( transport
) self
. doChildConnect
( name
, transport
) def remote_callTarget ( self
, command
, * args
, ** kw
) : '''遠(yuǎn)程調(diào)用方法@param commandId: int 指令號(hào)@param data: str 調(diào)用參數(shù)''' data
= self
. service
. callTarget
( command
, * args
, ** kw
) return data
總結(jié)
以上是生活随笔 為你收集整理的python firefly 游戏引擎 教程(二) 程序入口 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。