SocketBufferManager.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.Sockets;
  4. namespace IFramework.Net
  5. {
  6. internal class SocketBufferManager
  7. {
  8. int wTotalSize=0;
  9. int wCurIndex=0;
  10. int wBlockSize = 2048;
  11. LockParam lockParam = new LockParam();
  12. byte[] wBuffer=null;
  13. Queue<int> freeBufferIndexPool=null;
  14. /// <summary>
  15. /// 块缓冲区大小
  16. /// </summary>
  17. public int BlockSize { get { return wBlockSize; } }
  18. /// <summary>
  19. /// 缓冲区管理构造
  20. /// </summary>
  21. /// <param name="maxCounts"></param>
  22. /// <param name="blockSize"></param>
  23. public SocketBufferManager(int maxCounts, int blockSize)
  24. {
  25. if (blockSize < 4) blockSize = 4;
  26. this.wBlockSize = blockSize;
  27. this.wCurIndex = 0;
  28. wTotalSize = maxCounts * blockSize;
  29. wBuffer = new byte[wTotalSize];
  30. freeBufferIndexPool = new Queue<int>(maxCounts);
  31. }
  32. public void Clear()
  33. {
  34. using (LockWait lwait = new LockWait(ref lockParam))
  35. {
  36. freeBufferIndexPool.Clear();
  37. }
  38. }
  39. /// <summary>
  40. /// 设置缓冲区
  41. /// </summary>
  42. /// <param name="agrs"></param>
  43. /// <returns></returns>
  44. public bool SetBuffer(SocketAsyncEventArgs agrs)
  45. {
  46. using (LockWait lwait = new LockWait(ref lockParam))
  47. {
  48. if (freeBufferIndexPool.Count > 0)
  49. {
  50. agrs.SetBuffer(this.wBuffer, this.freeBufferIndexPool.Dequeue(), wBlockSize);
  51. }
  52. else
  53. {
  54. if ((wTotalSize - wBlockSize) < wCurIndex) return false;
  55. agrs.SetBuffer(this.wBuffer, this.wCurIndex, this.wBlockSize);
  56. this.wCurIndex += this.wBlockSize;
  57. }
  58. return true;
  59. }
  60. }
  61. /// <summary>
  62. /// 写入缓冲区
  63. /// </summary>
  64. /// <param name="agrs"></param>
  65. /// <param name="buffer"></param>
  66. /// <param name="offset"></param>
  67. /// <param name="cnt"></param>
  68. /// <returns></returns>
  69. public bool WriteBuffer(SocketAsyncEventArgs agrs, byte[] buffer, int offset, int cnt)
  70. {
  71. using (LockWait lwait = new LockWait(ref lockParam))
  72. {
  73. //超出缓冲区则不写入
  74. if (agrs.Offset + cnt > this.wBuffer.Length)
  75. {
  76. return false;
  77. }
  78. //超出块缓冲区则不写入
  79. if (cnt > wBlockSize) return false;
  80. Buffer.BlockCopy(buffer, offset, this.wBuffer, agrs.Offset, cnt);
  81. agrs.SetBuffer(this.wBuffer, agrs.Offset, cnt);
  82. return true;
  83. }
  84. }
  85. /// <summary>
  86. /// 释放缓冲区
  87. /// </summary>
  88. /// <param name="args"></param>
  89. public void FreeBuffer(SocketAsyncEventArgs args)
  90. {
  91. using (LockWait lwait = new LockWait(ref lockParam))
  92. {
  93. this.freeBufferIndexPool.Enqueue(args.Offset);
  94. args.SetBuffer(null, 0, 0);
  95. }
  96. }
  97. /// <summary>
  98. /// 自动按发送缓冲区的块大小分多次包
  99. /// </summary>
  100. /// <param name="buffer"></param>
  101. /// <param name="offset"></param>
  102. /// <param name="size"></param>
  103. /// <returns></returns>
  104. public ArraySegment<byte>[] BufferToSegments(byte[] buffer, int offset, int size)
  105. {
  106. if (size <= wBlockSize)
  107. return new ArraySegment<byte>[] { new ArraySegment<byte>(buffer, offset, size) };
  108. int bSize = wBlockSize;
  109. int bCnt = size / wBlockSize;
  110. int bOffset = 0;
  111. bool isRem = false;
  112. if (size % wBlockSize != 0)
  113. {
  114. isRem = true;
  115. bCnt += 1;
  116. }
  117. ArraySegment<byte>[] segItems = new ArraySegment<byte>[bCnt];
  118. for (int i = 0; i < bCnt; ++i)
  119. {
  120. bOffset = i * wBlockSize;
  121. if (i == (bCnt - 1) && isRem)
  122. {
  123. bSize = size - bOffset;
  124. }
  125. segItems[i] = new ArraySegment<byte>(buffer, offset + bOffset, bSize);
  126. }
  127. return segItems;
  128. }
  129. }
  130. }