一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - C#環形緩沖區(隊列)完全實現

C#環形緩沖區(隊列)完全實現

2021-12-02 13:47番茄炒西紅柿 C#

這篇文章主要為大家詳細介紹了C#環形緩沖區(隊列)完全實現代碼,感興趣的小伙伴們可以參考一下

公司項目中經常設計到串口通信,TCP通信,而且大多都是實時的大數據的傳輸,然后大家都知道協議通訊肯定涉及到什么,封包、拆包、粘包、校驗……什么鬼的概念一大堆,說簡單點兒就是要一個高效率可復用的緩存區。按照碼農的慣性思維就是去百度、谷歌搜索看有沒有現成的東西可以直接拿來用,然而我并沒有找到,好吧不是很難的東西自己實現一個唄。開扯…… 

為什么要用環形隊列?
環形隊列是在實際編程極為有用的數據結構,它有如下特點:
它是一個首尾相連的FIFO的數據結構,采用數組的線性空間,數據組織簡單。能很快知道隊列是否滿為空。能以很快速度的來存取數據。
因為有簡單高效的原因,甚至在硬件都實現了環形隊列。 

C#完全實現(可直接使用)
鄙人新手這份代碼肯定有不足之處,望大家指出交流,涉及到的多線程同步問題請調用者完成,不廢話直接上代碼。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
public class RingBufferManager
{
  public byte[] Buffer { get; set; } // 存放內存的數組
  public int DataCount { get; set; } // 寫入數據大小
  public int DataStart { get; set; } // 數據起始索引
  public int DataEnd { get; set; }  // 數據結束索引
  public RingBufferManager(int bufferSize)
  {
    DataCount = 0; DataStart = 0; DataEnd = 0;
    Buffer = new byte[bufferSize];
  }
 
  public byte this[int index]
  {
    get
    {
      if (index >= DataCount) throw new Exception("環形緩沖區異常,索引溢出");
      if (DataStart + index < Buffer.Length)
      {
        return Buffer[DataStart + index];
      }
      else
      {
        return Buffer[(DataStart + index) - Buffer.Length];
      }
    }
  }
 
  public int GetDataCount() // 獲得當前寫入的字節數
  {
    return DataCount;
  }
 
  public int GetReserveCount() // 獲得剩余的字節數
  {
    return Buffer.Length - DataCount;
  }
 
  public void Clear()
  {
    DataCount = 0;
  }
 
  public void Clear(int count) // 清空指定大小的數據
  {
    if (count >= DataCount) // 如果需要清理的數據大于現有數據大小,則全部清理
    {
      DataCount = 0;
      DataStart = 0;
      DataEnd = 0;
    }
    else
    {
      if (DataStart + count >= Buffer.Length)
      {
        DataStart = (DataStart + count) - Buffer.Length;
      }
      else
      {
        DataStart += count;
      }
      DataCount -= count;
    }
  }
 
  public void WriteBuffer(byte[] buffer, int offset, int count)
  {
    Int32 reserveCount = Buffer.Length - DataCount;
    if (reserveCount >= count)             // 可用空間夠使用
    {
      if (DataEnd + count < Buffer.Length)      // 數據沒到結尾
      {
        Array.Copy(buffer, offset, Buffer, DataEnd, count);
        DataEnd += count;
        DataCount += count;
      }
      else      // 數據結束索引超出結尾 循環到開始
      {
        System.Diagnostics.Debug.WriteLine("緩存重新開始....");
        Int32 overflowIndexLength = (DataEnd + count) - Buffer.Length;   // 超出索引長度
        Int32 endPushIndexLength = count - overflowIndexLength;       // 填充在末尾的數據長度
        Array.Copy(buffer, offset, Buffer, DataEnd, endPushIndexLength);
        DataEnd = 0;
        offset += endPushIndexLength;
        DataCount += endPushIndexLength;
        if (overflowIndexLength != 0)
        {
          Array.Copy(buffer, offset, Buffer, DataEnd, overflowIndexLength);
        }
        DataEnd += overflowIndexLength;                   // 結束索引
        DataCount += overflowIndexLength;                  // 緩存大小
      }
    }
    else
    {
      // 緩存溢出,不處理
    }
  }
 
  public void ReadBuffer(byte[] targetBytes,Int32 offset, Int32 count)
  {
    if (count > DataCount) throw new Exception("環形緩沖區異常,讀取長度大于數據長度");
    Int32 tempDataStart = DataStart;
    if (DataStart + count < Buffer.Length)
    {
      Array.Copy(Buffer, DataStart, targetBytes, offset, count);
    }
    else
    {
      Int32 overflowIndexLength = (DataStart + count) - Buffer.Length;  // 超出索引長度
      Int32 endPushIndexLength = count - overflowIndexLength;       // 填充在末尾的數據長度
      Array.Copy(Buffer, DataStart, targetBytes, offset, endPushIndexLength);
      
      offset += endPushIndexLength;
      
      if (overflowIndexLength != 0)
      {
        Array.Copy(Buffer, 0, targetBytes, offset, overflowIndexLength);
      }
    }
  }
 
 
  public void WriteBuffer(byte[] buffer)
  {
    WriteBuffer(buffer, 0, buffer.Length);
  }
 
}

調用實例
生產

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int len = sConn.Receive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, out se);
if (len <= 0) throw new Exception("disconnect..");
if (len > 0)
{
  lock (LockReceiveBuffer)
  {
    while (len + receiveBufferManager.DataCount > MAX_BUFFER_LEN)    // 緩存溢出處理
    {
      Monitor.Wait(LockReceiveBuffer,10000);
    }
    receiveBufferManager.WriteBuffer(receiveBuffer, 0, len);
    Monitor.PulseAll(LockReceiveBuffer);
  }
}

消費

?
1
2
3
4
5
6
lock (LockReceiveBuffer)
{
  freame_byte = new byte[frameLen];
  receiveBufferManager.ReadBuffer(freame_byte, 0, frameLen);
  receiveBufferManager.Clear(frameLen);

驗證 
TCP大數據連續測試一周沒出現問題內存問題。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/fanqie-liuxiao/p/5712094.html

延伸 · 閱讀

精彩推薦
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
主站蜘蛛池模板: 欧美日韩综合一区 | 国产成人福利免费视频 | 日本动漫黄网站在线观看 | 成人网欧美亚洲影视图片 | aaa大片| 日本中文字幕在线视频站 | 电车痴汉中文字幕 | 亚洲七七久久综合桃花 | 欧美福利在线观看 | 欧美男同video | 亚洲AV国产精品无码精 | 性色香蕉AV久久久天天网 | 久久99re8热在线播放 | 深夜免费在线视频 | 色老妇| 向日葵视频app下载18岁以下勿看 | 色多多视频网站 | 青青草成人在线 | 韩国免费特一级毛片 | 国产大秀视频 | 香蕉tv亚洲专区在线观看 | 小sao货ji巴cao死你视频 | futa百合高肉全h | 99ri在线精品视频在线播放 | 国产精品刺激好大好爽视频 | 成年极品漫画在线观看 | 亚洲经典激情春色另类 | 欧美午夜性春猛交bbb | 日韩精品一区二区三区老鸭窝 | 禁忌第一季第3季 | 天堂va在线高清一区 | 2020年新四虎免费 | 国产三及| 成人国产在线视频在线观看 | 91桃花| freesex1718处xx | 99热久久这里只有精品6国产网 | 国产二区视频在线观看 | 欧美人与禽杂交大片 | 精品国产一区二区三区久久久蜜臀 | 欧美一级片在线免费观看 |