网络游戏中网络模块浅析
在網(wǎng)絡游戲中,不論是服務端還是客戶端都需要網(wǎng)絡通訊的功能模塊,而一個優(yōu)秀的成熟的網(wǎng)絡通訊模塊,又可以用于多個游戲產(chǎn)品中。
?
于是,在學習的過程中,設計和實現(xiàn)一個可復用的網(wǎng)絡通訊模塊,變得非常的有意義。
?
???????? 通過思考我們可以一步一步的來實現(xiàn)這樣的模塊:
?
我們應該知道對原生的Socket API進行封裝是有必要的,也許當前服務端是運行在window環(huán)境下,也許改天就有可能要在Linux下面運行。而對原生Socket API進行封裝,可以很方便的讓我們進行兩者的切換,并且不需要我們付出多大的代價。
可以像下面這樣封裝,放在SOCKET_API命名空間下面,其他API類似:
UINT SOCKET_API::recv_ex ( SOCKET s , void * buf , UINT len , UINT flags )
{
???????? #if defined __LINUX__
???? ???????? ….
#elif defined __WINDOWS__
???? ???????? ….
#endif
}
?
我們都知道游戲通常都是使用TCP來實現(xiàn)通訊的,而TCP需要下面這些最基本的功能及對SOCKET進行設置或者獲取信息的函數(shù)。
| server | client |
| bind listen accept send recv close | connect send recv close |
我們希望把這些功能都封閉到一個CSocket類中。
class CSocket
{
public :
???? 構(gòu)造函數(shù),析構(gòu)函數(shù),初始化函數(shù)……
???? BOOL connect (const CHAR* host, UINT port) ;
????????????? UINT send (const VOID* buf, UINT len, UINT flags = 0) ;
???? SOCKET accept( struct sockaddr* addr, UINT* addrlen ) ;
其他函數(shù),例如receive ,bind,listen,close,get和set變量接口,有效性判斷等等……
public :
???? ???????? SOCKET m_SocketID;
???? ???????? SOCKADDR_IN m_SockAddr;
???? ???????? CHAR m_Host[IP_SIZE];
???? ???????? UINT m_Port;
}
不論是服務端還是客戶端都沒有辦法做到一收到消息就馬上響應請求,然后直接把
這個消息丟棄掉。所以我們需要有一個地方可以保存這些消息,這時我們可以定義輸入和輸出消息緩沖區(qū)的類,當我們發(fā)送或者接收消息時,先把消息放到相應的消息緩沖區(qū)里,然后再進行相應的處理。而這個緩沖區(qū)最好是環(huán)形的,當緩沖區(qū)不夠用的時候能夠自己增加緩沖區(qū)大小,當然需要有個上限。
?
當我們有了消息緩沖區(qū)后,這時我們需要通過一種方式,把消息放入緩沖區(qū)和從緩
沖區(qū)中把消息讀取出來,在放入和取出的時候可能還需要伴隨著加密與解密操作。由于在游戲中,一樣連接通常都代表著一個玩家。
???????? 我們可以定義個CPlayer類:
???????? class CPlayer
{
public:
???????? ProcessInput();???????? //讀取網(wǎng)絡上的消息并放在輸入消息緩沖區(qū)
???????? ProcessOutput();???? //把輸出消息緩沖區(qū)中的消息發(fā)送出去
???????? ProcessMsg();????????? //處理收到的消息,把相應的消息交給相應的處理函數(shù)
private:
???????? 輸入緩沖區(qū)
???????? 輸出緩沖區(qū)
}
?
到這里時,上面的內(nèi)容通常都可以作為服務端和客戶端通用的代碼。
?
下面我們重點了解一下,服務端是怎么樣接著處理收到的消息的,在我接觸過的服務端中,有兩種不同的框架,不過處理方式大同小異,順便提下。
?
第一種,就像我在游戲服務端邏輯模塊處理框架中說的差不多,在種情況之下,服務端的邏輯模塊會劃分成很多的DLL模塊,比如:
?
戰(zhàn)斗系統(tǒng)就是一個BattleSys.dll
技能系統(tǒng)就是一個MagicMgr.dll
角色系統(tǒng)就是一個RoleMgr.dll
?
然后我們有一個消息中心,當網(wǎng)絡模塊收到消息之后把消息發(fā)送給消息中心,消息中心再把消息Buffer發(fā)送給感興趣的DLL模塊,然后這些DLL模塊用消息Buffer生成相應的CMsg(每個消息都有消息頭,根據(jù)消息頭的消息編號可以識別相應的CMsg),并執(zhí)行CMsg的ProcessMsg消息處理函數(shù)。
?
第二種,沒有把邏輯模塊劃分成很多個DLL,游戲邏輯都在Server中進行處理。收到網(wǎng)絡消息之后,直接通過管理器類CpacketFactoryMgr創(chuàng)建出CMsg類(查找相應的消息創(chuàng)建工廠,并用它創(chuàng)建出CMsg類),并執(zhí)行CMsg的ProcessMsg消息處理函數(shù)。
?
其實就是這樣的過程,注冊XXX到管理器 => 通過XXX的ID到管理器中找到XXX => XXX.DoSomething()
?
先說到這里了…繼續(xù)學習之后再繼續(xù)……
總結(jié)
以上是生活随笔為你收集整理的网络游戏中网络模块浅析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入探讨傅立叶变换、拉普拉斯变换、Z变换
- 下一篇: FIR数字滤波器设计_窗函数法