近些天寫(xiě)了一些游戲邏輯,發(fā)現(xiàn)項(xiàng)目組在寫(xiě)C/S網(wǎng)絡(luò)消息包的時(shí)候,根據(jù)作用的不同,定義了很多的不同的消息格式。比如,所有的消息包都繼承自下面這個(gè)基本結(jié)構(gòu)。
struct?SPacket


{
??byte??bType;
}然后,添加物品的消息包,設(shè)置成員狀態(tài)的消息包都分別定義了不同的結(jié)構(gòu)。
struct?SAddItemPacket?:?public?SPacket


{
??SItem?item;
??SAddItem()

??
{
????bType?=?STC_AddItem;
??}
}

struct?SSetMemberPacket?:?public??SPacket


{
??byte??bStatus;
??SSetMemberPacket()

??
{
????bType?=?STC_SetMember;
??}
}隨著項(xiàng)目填充越來(lái)越多的內(nèi)容,消息包的類型越來(lái)越多,不能避免嗎?
晚上睡覺(jué)的時(shí)候,想著如果把網(wǎng)絡(luò)引擎引入項(xiàng)目之類的會(huì)怎樣呢?然后想到看過(guò)的ICE教程,就大概的思考類似ICE這樣的通用RPC大概是怎樣實(shí)現(xiàn)的。
RPC由服務(wù)對(duì)象以及其客戶端的表現(xiàn)——代理對(duì)象構(gòu)成。客戶端代碼中,調(diào)用了代理對(duì)象的某個(gè)接口,就會(huì)導(dǎo)致其服務(wù)對(duì)象執(zhí)行該接口的實(shí)現(xiàn),使得客戶端看起來(lái)就像是執(zhí)行本地調(diào)用一樣。
因此RPC的直觀概念是接口調(diào)用的網(wǎng)絡(luò)映射,核心內(nèi)容是:如何將客戶端調(diào)用(某個(gè)對(duì)象的)某個(gè)接口的這一行為進(jìn)行通用的序列化?
對(duì)調(diào)用行為序列化和對(duì)對(duì)象序列化是不同的,而且RPC的目標(biāo)是對(duì)任何類型的接口調(diào)用行為都能有一個(gè)通用的序列化方案。
我們要調(diào)用某個(gè)接口的時(shí)候,下達(dá)的命令通常是,“某某類型的,那個(gè)誰(shuí),把你的那個(gè)名叫什么的方法調(diào)用一下,參數(shù)是這些,a,b,c,d”。這樣我們就進(jìn)行了一次接口調(diào)用。因此,調(diào)用行為最基本的序列化方法是,類型ID+方法ID+對(duì)象ID+參數(shù)。將這些數(shù)據(jù)加成起來(lái),就能作為一個(gè)調(diào)用消息包由客戶端發(fā)向服務(wù)器,服務(wù)器處理RPC管理的對(duì)象將會(huì)根據(jù)類ID,對(duì)象ID找到服務(wù)對(duì)象,然后根據(jù)方法ID,找到方法,并能根據(jù)方法知道有幾個(gè)參數(shù),以及參數(shù)的類型,最終執(zhí)行調(diào)用。
因此,我此時(shí)覺(jué)得,像項(xiàng)目組現(xiàn)在定義的多種大小不變,種類繁多的消息格式,其實(shí)都可以用一個(gè)能序列化調(diào)用行為的消息包來(lái)解決。該消息包的結(jié)構(gòu)是:
class??SPacket


{
??WORD??wClassID;
??WORD??wMemberFuncID;
??BYTE??bParam[PACKET_PARAM_BUFFER_SIZE];
??QWORD??qwBufferOffset?=?0;

public:
??SPacket(WORD?par_wClassID,WORD?par_FuncID,?DWORD?dwObjID);
??SPacket(WORD?par_wClassID,WORD?par_FuncID,?QWORD?qwObjID);

??template<typename?T>
??bool??Push(T?value)

??
{
????memcpy(bParam?+?qwBufferOffset,value,sizeof(T);
????qwBufferOffset?+=?sizeof(T);
??}

??bool??Pop(T?&value)

??
{
????T??*pValue?=?static_cast<T*>(bParam?+?qwBufferOffset)
????value?=?*pValue;
????qwBufferOffset?+=?sizeof(T);
??}

??QWORD??Size()?const

??
{
????return??sizeof(wClassID)?+?sizeof(wMemberFuncID)?+?qwBufferOffset;
??}
};參數(shù)從左到右裝入消息包,相應(yīng)的也是從左到右從消息包取出,來(lái)配合服務(wù)器端執(zhí)行相應(yīng)的函數(shù)。
posted on 2007-01-26 23:26
LOGOS 閱讀(2504)
評(píng)論(12) 編輯 收藏 引用