struct?SPacket

{
??byte??bType;
}
struct?SAddItemPacket?:?public?SPacket

{
??SItem?item;
??SAddItem()
??
{
????bType?=?STC_AddItem;
??}
}
struct?SSetMemberPacket?:?public??SPacket

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

