RMI
和INetworkModule一樣,IRMIModule也是一種進程間通信的機制。而且RMI制定了傳輸協議,它使用一個字符串常量綁定到一個回調函數,並通過序列化的數據進行數據傳輸。
RMI組成
一個RMI模型的成分可以是:
-
常駐內存的RMI服務類型,繼承自RMIObject
-
臨時的RMI客戶類型,繼承自RMIProxyObject
-
綁定到一個RMI請求的返回類型,繼承自RMIBackObject,它屬於客戶類型的成分
我們必須自己實現這些類型的派生類型。在項目中,服務類型和客戶類型大都已經創建完畢,你只需要修改裏面的方法即可。比如,一個從loginserver到dataaccess之間的RMI模型爲:
-
服務類型:RMILoginObject
-
客戶類型:RMILoginClient
項目中只有dataaccess提供RMI服務,其餘進程若要和dataaccess通信,必須使用RMI。
RMI調用的流程
當dataaccess啓動RMI服務後,客戶端(這裏的客戶端是指loginserver、gameworld等服務端進程)就可以創建RMI會話(rmi::Session)了。必須保存該會話,以後將通過會話來發送RMI請求。這一個步驟不需要我們操心,因爲都已經寫好了。
當我們需要發起一個RMI請求時,就要創建一個RMI客戶對象,然後綁定到RMI會話,並創建一個RMI返回對象,它將獲得返回的數據。RMI請求由RMI客戶對象發起。
可以把RMI類比成一個普通的函數調用,RMI服務對象就是被調函數,RMI客戶對象就是主調函數,RMI返回對象就是函數的返回值,只不過這個它是一種序列化數據,因此更爲複雜。函數的參數也是一種序列化數據。
我們通過這樣一個函數發起RMI請求:
/*
RMI調用
@session 對該session調用RMI
@module 遠端模塊名
@method 遠端方法名
@in_stream 遠端調用的輸入參數
@backobj 返回時的調用對象,注意:該對象由RMI模塊在返回調用後調用Free銷燬
@remotec_syn 遠端是否阻塞調用
@return 是否成功提交call請求
*/
bool IRMIModule::Call(const rmi::Session &session,
const char *module, const char *method,
const TLVSerializer &in_stream, rmi::RMIBackObject *backobj,
bool remotec_syn=true, unsigned long timeout=10000)=0;
由於會話綁定了IRMIModule,因此有能力調用Call。大家需要結合實際案例去理解,尤其是RMI調用的流程,一定要搞清楚。
RMI處理函數
RMI處理函數由RMI服務類型定義,它有着固定的類型:
int (*)(TLVUnserializer &in_param, TLVSerializer *out_param);
由於有着固定的定義,所以這些函數可以存放到一張函數表中。表的索引就是上述Call函數的method參數。in_param就是上述Call函數的in_stream,而out_param將傳遞給backobj作爲返回數據。
Note
TLVSerializer和TLVUnserializer是可以互相轉換的,因爲它們本質上是一個buffer。如果你細心的話,會發現in_param和in_stream類型不一致,但實際上其真實的數據是一致的。
函數的返回類型定義在枚舉:ERMIDispatchStatus,它的定義如:
enum ERMIDispatchStatus
{
DispatchOK,
DispatchObjectNotExist,
DispatchMethodNotExist,
DispatchParamError,
DispatchOutParamBuffTooShort,
SessionDisconnect,
};
如果調用成功,我們需要返回DispatchOK。如果反序列化失敗,通常返回DispatchParamError,如果序列化失敗(Push),通常調用DispatchOutParamBuffTooShort。其餘返回值由底層代碼處理。
關於DispatchOutParamBuffTooShort
項目中你看到有些情況返回了DispatchOutParamBuffTooShort,並打印了一條Critical日誌,看上去很嚇人。我認爲這應當是一種編程失誤(可能有極個別情況的確是Critical),這是由於沒有理解前人這樣寫,後人又只會照着抄的緣故。那麼,這個返回值意味着什麼呢?意味着序列化所需要的buffer不足了,底層代碼會開闢一塊更大的空間,然後重新調用處理函數。