服務器程序設計部分
續上在這里我將要向大家簡單介紹一下游戲服務器中必須要處理另外一項主要技術:
內存分配處理技術也可以稱為內存池處理技術(這個比較洋氣,前面通俗的好,呵呵)
開始向大家介紹一般情況下我們對于內存的一些基本操作。簡單而言,內存操作就只有三個步驟:申請、使用、銷毀。而對于這些操作我們在C和C++中的處理方式略有不同:
在C中我們一般用malloc(….)函數來進行申請,而對應銷毀已經申請的內存使用free(…)函數。
在C++我們一般使用new操作符和delete操作符進行處理申請和銷毀。
大家一定要問了,我們一般都是這樣處理的呀!!沒有什么可以說的哦!!呵呵,我感覺就有還是有一些東東和大家聊的哦。先聊簡單幾條吧!!
1.Malloc(…..)和free(….), new ….和 delete …必須成對出現不可以混雜哦,混雜的話,后果就不可以想了哦!!(也沒有什么,就是內存被泄漏了,呵呵)
2.在我們使用new …和delete ….一定要注意一些細節,否則后果同上哦!!什么細節呢?下面看一個簡單的例子:
char *block_memory = NULL;
block_memory = new char[1024];
delete block_memory;
block_memory = NULL;
大家沉思一會。。。。。。。。。
大家看有錯嗎?沒有錯吧!!
如果說沒有錯的,就要好好補補課了,是有錯的,上面實際申請的內存是沒有完全被釋放的,為什么呢?因為大家沒有注意第一條的完全匹配原則哦,在new 的時候有[ ],我們在delete 怎么就沒有看見[ ] 的影子呢? 這就造成了大錯有1023個字節沒有被釋放。正確的是 : delete []block_memory;
關于內存基本操作的我是說這兩條,其他要注意還是有的,基本就源于此了。
了解了上面那些接下來就想大家說說服務器內存處理技術了。上面都沒有弄清楚了,就算了。呵呵。
大家都知道,我們的服務器要頻繁的響應客戶端的消息同時要將消息發送到客戶端,并且還要處理服務器后臺游戲World的運行。這樣我們就必須要大量的使用內存,并且要進行大量的內存操作(申請和銷毀)。而在這樣的操作中,我們還必須要保證我們的絕對正確無誤,否則就會造成內存的泄漏,而內存泄漏對于服務器而言是非常可怕的,也可能就是我們服務器設計失敗的毒藥。而我們如何進行服務器內存的正確和合理的管理呢?那就是我們
必須建立一套適合我們自己的內存管理技術。現在就向大家說一說我在內存管理方面的一些做法。
基本原理先用圖形表示一下:
回收內存塊
超大塊內存
現在要申請的內存塊
上面的意思是:我們在服務器啟動過程中就為自己申請一塊比較大的內存塊,而我們在服務器運行過程中需要使用內存我們就到這樣一塊比較大已經申請好的內存塊中去取。而使用完后要進行回收。原理就是這么簡單。而最重要的是我們如何管理這個大的內存塊呢?
(非常復雜也比較難,呵呵)
首先 就內存塊操作而言就只有申請(類似 new)和回收(類似 delete)。
其次 我們必須要清楚那些內存我們在使用中,那些是可以申請的。
關于上面我簡單將這樣的一些數據結構和class定義在下面供大家參考使用。
typedef struct MemoryBlock //內存塊結構
{
void *buffer; //內存塊指針
int b_Size; //內存塊尺寸
} MemoryBlock;
class CMemoryList //列表對象類(相當于數組管理類)
{
public:
CMemoryList();
virtual ~ CMemoryList();
void InitList(int data_size,int data_num);//初始化列表數據結構尺寸和數量
void AddToList(void *data); //加入列表中
void DeleteItem(int index); //刪除指定索引元素
……………..
private:
void Init();
void Release();
private:
void *memory;
int total_size;
int total_num;
protected:
};
classs CMemoryPool //內存池處理類
{
public:
CMemoryPool();
virtual ~ CMemoryPool();
bool InitMemoryPool(int size); //初始化內存池
void * ApplicationMemory(int size); //申請指定size內存
void CallBackMemory(void *,int size); //回收指定size內存
private:
void Init();
void Release():
MemoryBlock *UniteMemory(MemoryBlock *block_a,MemoryBlock * block_b); //合并內存
private:
MemoryBlock memoryPool_Block; //內存池塊
CMemoryList *callBackMemory_List; //回收內存列表
CMemoryList *usingMemory_List; //使用中內存列表
CMemoryList *spacingMemory_List; //空白內存列表
protected:
};
以上就是這個內存管理類的一些基本操作和數據定義,class CMemoryList 在這里不是重點暫且就不說了,有空再聊。而具體的內存池處理方法簡單敘述如下:
函數InitMemoryPool(): 初始化申請一塊超大內存。
函數ApplicationMemory():申請指定尺寸,申請內存成功后,要將成功申請的內存及其尺寸標示到usingMemory_List列表,同時要將spacingMemory_List列表進行重新分配。以便于正確管理。
函數CallBackMemory():回收指定尺寸內存,成功回收后,要修改spacingMemory_List列表,同時如果有相鄰的內存塊就要合并成一個大的內存塊。usingMemory_List修改使用列表,要在使用列表中的這一項刪除。
以上就是一些簡單處理說明,更加詳細的就需要大家自己琢磨和處理了。我就不細說了。呵呵。不足之處就請大家進行指正,以便讓我們大家都提高。先謝謝了。