鑑於我之前對於遊戲的網絡開發部分沒有經驗。後面關於ET消息系統的學習都將參考這位朋友Norman_Lin的博客來學習。後面會自己再來調整文章的順序,結構等。
-
CircularBuffer
這個應該是ET框架中消息相關的類,繼承自Stream類。ChunkSize字段的代表一個字節數組的最大長度。後面兩個隊列應該是用於存儲消息流的。
public int ChunkSize = 8192;
private readonly Queue<byte[]> bufferQueue = new Queue<byte[]>();
private readonly Queue<byte[]> bufferCache = new Queue<byte[]>();
public int LastIndex { get; set; }
public int FirstIndex { get; set; }
private byte[] lastBuffer;
Length字段的定義和bufferQueue隊列的長度有關,撇開特殊情況不說,結果如下:
Lenght = (this.bufferQueue.Count - 1) * ChunkSize + this.LastIndex - this.FirstIndex;
CircularBuffer在實例化是會執行AddLast方法,會將bufferCache隊列中的對頭元素彈出(不存在則創建一個空的元素,長度爲ChunkSize),做兩次賦值:
this.bufferQueue.Enqueue(buffer);
this.lastBuffer = buffer;
後面還有幾個對bufferQueue隊列做操作的方法,獲取bufferQueue隊列的對頭和隊尾元素,移除對頭元素(重新壓入bufferCache隊列中)。
後面的幾個方法是對字節數組和Stream間的互相操作,關於Stream類,可以參考這篇文章。Write方法用於將steam流寫入到bufferQueue隊列的尾部字節數組中去。在獲取到流中還有數據後,通過一個While循環來寫數據(alreadyCopyCount 和count做判斷)。當字節數組還有位置時,就從流中寫入數據到數組中去。Read方法用於將bufferQueue隊列的頭部字節數組中的數據轉入到流中去。邏輯和Write方法差不多,就是反一下。
// 從stream寫入CircularBuffer
public void Write(Stream stream)
{
int count = (int)(stream.Length - stream.Position); // 當前流中剩下的數據長度
int alreadyCopyCount = 0; // alreadyCopyCount 代表已經從流中寫入的長度(臨時的)
while (alreadyCopyCount < count)
{
// this.LastIndex是一個遊標,代表已經寫入到數組中的數據長度
if (this.LastIndex == ChunkSize)
{
// 對隊列擴容
this.AddLast();
this.LastIndex = 0;
}
int n = count - alreadyCopyCount; // n 代表流中還未寫入的數據的長度
// 數組的長度 - 已經寫入的長度 > 流中還未寫入的數據的長度
if (ChunkSize - this.LastIndex > n)
{
stream.Read(this.lastBuffer, this.LastIndex, n);
// 寫入完成後的長度
this.LastIndex += count - alreadyCopyCount;
alreadyCopyCount += n;
}
else // 數組中的長度不夠,先寫滿,然後擴容再將剩餘的寫入
{
stream.Read(this.lastBuffer, this.LastIndex, ChunkSize - this.LastIndex);
alreadyCopyCount += ChunkSize - this.LastIndex;
this.LastIndex = ChunkSize;
}
}
}