c# 完成端口模型IOCP 网络NETWORK TCP/UDP通信 常用 字节byte环绕缓冲区 FIFO 内存池 源码

接受到的数据,使用环绕缓冲区来解决粘包和半包的处理

    /// <summary>
    /// 接受到的数据,使用环绕缓冲区来解决粘包和半包的处理
    /// </summary>
    [MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
    public class ReceiveQueue
    {
        #region zh-CHS 类常量 | en Class Constants
        /// <summary>
        /// 字节默认的大小
        /// </summary>
        private const long BUFFER_SIZE = 2048;
        #endregion

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 字节的头位置
        /// </summary>
        private long m_Head = 0;
        /// <summary>
        /// 字节的尾位置
        /// </summary>
        private long m_Tail = 0;
        /// <summary>
        /// 字节的数组
        /// </summary>
        private byte[] m_Buffer = new byte[BUFFER_SIZE];
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockBuffer = new SpinLock();
        #endregion

        #region zh-CHS 属性 | en Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 字节的大小
        /// </summary>
        private long m_Size = 0;
        #endregion
        /// <summary>
        /// 环绕缓冲区内的数据大小
        /// </summary>
        public long Length
        {
            get { return m_Size; }
        }
        #endregion

        #region zh-CHS 方法 | en Method
        /// <summary>
        /// 给出使用环绕缓冲区内的数据
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iOffset"></param>
        /// <param name="iSize"></param>
        /// <returns>返回实际读取到的字节数</returns>
        public long Dequeue( ref byte[] byteBuffer, long iOffset, long iSize )
        {
            if ( iSize == 0 )
                return 0;

            if ( iSize > m_Size )
                iSize = m_Size;

            m_LockBuffer.Enter();
            {
                if ( m_Head < m_Tail )
                    Buffer.BlockCopy( m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)iSize );
                else
                {
                    long rightLength = m_Buffer.Length - m_Head;

                    if ( rightLength >= iSize )
                        Buffer.BlockCopy( m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)iSize );
                    else
                    {
                        Buffer.BlockCopy( m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)rightLength );
                        Buffer.BlockCopy( m_Buffer, 0, byteBuffer, (int)( iOffset + rightLength ), (int)( iSize - rightLength ) );
                    }
                }

                m_Head = ( m_Head + iSize ) % m_Buffer.Length;
                m_Size -= iSize;

                if ( m_Size == 0 )
                {
                    m_Head = 0;
                    m_Tail = 0;
                }
            }
            m_LockBuffer.Exit();

            return iSize;
        }

        /// <summary>
        /// 压入数据至环绕缓冲区内
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iOffset"></param>
        /// <param name="iSize"></param>
        public void Enqueue( byte[] byteBuffer, long iOffset, long iSize )
        {
            m_LockBuffer.Enter();
            {
                if ( ( m_Size + iSize ) > m_Buffer.Length )
                    SetCapacity( ( m_Size + iSize + 2047 ) & ~2047 ); // 总是以2048的倍数来增大字节数, :( 弄得我老半天才明白原理呢!

                if ( m_Head < m_Tail )
                {
                    long rightLength = m_Buffer.Length - m_Tail;

                    if ( rightLength >= iSize )
                        Buffer.BlockCopy( byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)iSize );
                    else
                    {
                        Buffer.BlockCopy( byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)rightLength );
                        Buffer.BlockCopy( byteBuffer, (int)( iOffset + rightLength ), m_Buffer, 0, (int)( iSize - rightLength ) );
                    }
                }
                else
                    Buffer.BlockCopy( byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)iSize );

                m_Tail = ( m_Tail + iSize ) % m_Buffer.Length;
                m_Size += iSize;
            }
            m_LockBuffer.Exit();
        }

        /// <summary>
        /// 压入数据至环绕缓冲区内
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iOffset"></param>
        /// <param name="iSize"></param>
        public void Enqueue( IntPtr byteBuffer, long iOffset, long iSize )
        {
            m_LockBuffer.Enter();
            {
                if ( ( m_Size + iSize ) > m_Buffer.Length )
                    SetCapacity( ( m_Size + iSize + 2047 ) & ~2047 ); // 总是以2048的倍数来增大字节数, :( 弄得我我半天才明白原理呢!

                IntPtr byteBufferOffset;
                if ( m_Head < m_Tail )
                {
                    long rightLength = m_Buffer.Length - m_Tail;

                    if ( rightLength >= iSize )
                    {
                        byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset );
                        Marshal.Copy( byteBufferOffset, m_Buffer, (int)m_Tail, (int)iSize );
                    }
                    else
                    {
                        byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset );
                        Marshal.Copy( byteBuffer, m_Buffer, (int)m_Tail, (int)rightLength );

                        byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset + rightLength );
                        Marshal.Copy( byteBuffer, m_Buffer, 0, (int)( iSize - rightLength ) );
                    }
                }
                else
                {
                    byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset );
                    Marshal.Copy( byteBuffer, m_Buffer, (int)m_Tail, (int)iSize );
                }

                m_Tail = ( m_Tail + iSize ) % m_Buffer.Length; // 返回环绕的数据的位置
                m_Size += iSize;
            }
            m_LockBuffer.Exit();
        }

        /// <summary>
        /// 清除数据的信息,不清除数据缓冲,用于下次使用
        /// </summary>
        public void Clear()
        {
            m_LockBuffer.Enter();
            {
                m_Head = 0;
                m_Tail = 0;
                m_Size = 0;
            }
            m_LockBuffer.Exit();
        }

        /// <summary>
        /// 给出数据包的长度
        /// </summary>
        /// <returns></returns>
        public long GetPacketLength()
        {
            long iReturn = 0;

            m_LockBuffer.Enter();
            {
                EventHandler<PacketLengthInfoEventArgs> tempEvent = s_ThreadEventPacketLength;
                if ( tempEvent != null )
                {
                    PacketLengthInfoEventArgs packetLengthInfoEventArgs = new PacketLengthInfoEventArgs( m_Buffer, m_Size, m_Head );
                    tempEvent( this, packetLengthInfoEventArgs );
                    iReturn = packetLengthInfoEventArgs.PacketLength;
                }
            }
            m_LockBuffer.Exit();

            return iReturn;
        }

        /// <summary>
        /// 给出数据包的ID
        /// </summary>
        /// <returns></returns>
        public long GetPacketID()
        {
            long iReturn = 0;

            m_LockBuffer.Enter();
            {
                EventHandler<PacketIdInfoEventArgs> tempEvent = s_ThreadEventPacketID;
                if ( tempEvent != null )
                {
                    PacketIdInfoEventArgs packetIdInfoEventArgs = new PacketIdInfoEventArgs( m_Buffer, m_Size, m_Head );
                    tempEvent( this, packetIdInfoEventArgs );
                    iReturn = packetIdInfoEventArgs.PacketId;
                }
            }
            m_LockBuffer.Exit();

            return iReturn;
        }

        /// <summary>
        /// 给出数据包的ID
        /// </summary>
        /// <returns></returns>
        public PacketHeadT GetPacketHead<PacketHeadT>( EventHandler<PacketHeadInfoEventArgs<PacketHeadT>> eventHandler )
        {
            if ( eventHandler == null )
                throw new Exception( "ReceiveQueue.GetPacketHead<.>(...) - eventHandler == null error!" );

            PacketHeadT returnT = default( PacketHeadT );

            m_LockBuffer.Enter();
            {
                PacketHeadInfoEventArgs<PacketHeadT> eventArgs = new PacketHeadInfoEventArgs<PacketHeadT>( m_Buffer, m_Size, m_Head );
                eventHandler( this, eventArgs );
                returnT = eventArgs.PacketHead;
            }
            m_LockBuffer.Exit();

            return returnT;
        }
        #endregion

        #region zh-CHS 内部方法 | en Internal Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前的类是否已锁
        /// </summary>
        private LockInOut m_bIsLockThis = new LockInOut( false );
        #endregion
        /// <summary>
        /// 锁定当前的类(表示当前类正在调用中)
        /// </summary>
        /// <returns>返回是否已经锁定成功</returns>
        internal bool InProcessReceive()
        {
            return m_bIsLockThis.InLock();
        }

        /// <summary>
        /// 释放当前已经锁定的类(表示当前类的调用已结束)
        /// </summary>
        internal void OutProcessReceive()
        {
            m_bIsLockThis.OutLock();
        }
        #endregion

        #region zh-CHS 私有方法 | en Private Method
        /// <summary>
        /// 扩大缓冲数据的大小(当前都在锁中操作,因此不需要锁定的)
        /// </summary>
        /// <param name="iCapacity"></param>
        private void SetCapacity( long iCapacity )
        {
            byte[] newBuffer = new byte[iCapacity];

            if ( m_Size > 0 )
            {
                if ( m_Head < m_Tail )
                    Buffer.BlockCopy( m_Buffer, (int)m_Head, newBuffer, 0, (int)m_Size );
                else
                {
                    Buffer.BlockCopy( m_Buffer, (int)m_Head, newBuffer, 0, (int)( m_Buffer.Length - m_Head ) );
                    Buffer.BlockCopy( m_Buffer, 0, newBuffer, (int)( m_Buffer.Length - m_Head ), (int)m_Tail );
                }
            }

            m_Head = 0;
            m_Tail = m_Size;
            m_Buffer = newBuffer;
        }
        #endregion

        #region zh-CHS 共有事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<PacketLengthInfoEventArgs> s_ThreadEventPacketLength;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock s_LockThreadEventPacketLength = new SpinLock();
        #endregion
        /// <summary>
        /// 获取接收到的数据包长度
        /// </summary>
        public event EventHandler<PacketLengthInfoEventArgs> ThreadEventPacketLength
        {
            add
            {
                s_LockThreadEventPacketLength.Enter();
                {
                    s_ThreadEventPacketLength += value;
                }
                s_LockThreadEventPacketLength.Exit();
            }
            remove
            {
                s_LockThreadEventPacketLength.Enter();
                {
                    s_ThreadEventPacketLength -= value;
                }
                s_LockThreadEventPacketLength.Exit();
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<PacketIdInfoEventArgs> s_ThreadEventPacketID;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock s_LockThreadEventPacketID = new SpinLock();
        #endregion
        /// <summary>
        /// 获取接收到的数据包长度
        /// </summary>
        public event EventHandler<PacketIdInfoEventArgs> ThreadEventPacketID
        {
            add
            {
                s_LockThreadEventPacketID.Enter();
                {
                    s_ThreadEventPacketID += value;
                }
                s_LockThreadEventPacketID.Exit();
            }
            remove
            {
                s_LockThreadEventPacketID.Enter();
                {
                    s_ThreadEventPacketID -= value;
                }
                s_LockThreadEventPacketID.Exit();
            }
        }
        #endregion
    }

发送字节缓存

  /// <summary>
    /// 
    /// </summary>
    internal struct SendBuffer
    {
        #region zh-CHS 共有常量 | en Public Constants
        /// <summary>
        /// 
        /// </summary>
        public readonly static SendBuffer NullBuffer = new SendBuffer( null );
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 私有的构造类
        /// </summary>
        private SendBuffer( byte[] buffer )
        {
            m_Buffer = buffer;
            m_Length = 0;
        }
        #endregion

        #region zh-CHS 属性 | en Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 缓冲区的字节
        /// </summary>
        private byte[] m_Buffer;
        #endregion
        /// <summary>
        /// 缓冲区的字节
        /// </summary>
        public byte[] Buffer
        {
            get { return m_Buffer; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 缓冲区的长度
        /// </summary>
        private long m_Length;
        #endregion
        /// <summary>
        /// 缓冲区已写入的长度
        /// </summary>
        public long Length
        {
            get { return m_Length; }
        }

        /// <summary>
        /// 缓冲区的剩余的有效空间
        /// </summary>
        public long SpareSpace
        {
            get { return ( m_Buffer.Length - m_Length ); }
        }

        /// <summary>
        /// 缓冲区是否已经满了
        /// </summary>
        public bool IsFull
        {
            get { return ( m_Length >= m_Buffer.Length ); }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsNull
        {
            get { return m_Buffer == null; }
        }
        #endregion

        #region zh-CHS 方法 | en Method
        /// <summary>
        /// 
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iOffset"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        public long Write( byte[] byteBuffer, long lOffset, long lLength )
        {
            // 获取可以写当前缓冲区的字节数
            long iWrite = Math.Min( lLength, this.SpareSpace );

            // 写入数据
            System.Buffer.BlockCopy( byteBuffer, (int)lOffset, m_Buffer, (int)m_Length, (int)iWrite );

            // 跟新缓冲区的长度
            m_Length += iWrite;

            return iWrite;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Release()
        {
            if ( m_Buffer == null )
                return;

            // 把数据返回进内存池
            SendQueue.ReleaseBuffer( m_Buffer );

            m_Buffer = null;
            m_Length = 0;
        }
        #endregion

        #region zh-CHS 静态方法 | en Static Method
        /// <summary>
        /// 请求Gram类
        /// </summary>
        /// <returns></returns>
        public static SendBuffer Instance()
        {
            return new SendBuffer( SendQueue.AcquireBuffer() );
        }
        #endregion
    }

    /// <summary>
    /// 数据输出包的缓冲区,如果数据过长就等处理缓存发送时发送数据( 小于 512K 时 )
    /// 之所以小于 512K 是因为TCP-IP发送数据时总是发送至客户端彼此确认完毕后才通知返回的,如果过大网络延迟时会严重影响网络的通讯.
    /// </summary>
    [MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
    internal class SendQueue
    {
        #region zh-CHS 私有成员变量 | en Private Member Variables
        #region zh-CHS 私有常量 | en Private Constants
        /// <summary>
        /// 
        /// </summary>
        private readonly static int QUEUE_CAPACITY_SIZE = 1024;
        #endregion
        /// <summary>
        /// 当Flush发出的数据(最后发出的数据块)
        /// </summary>
        private SendBuffer m_FlushBuffer = SendBuffer.NullBuffer;
        /// <summary>
        /// 等待需要发出的数据
        /// </summary>
        private Queue<SendBuffer> m_PendingBuffer = new Queue<SendBuffer>( QUEUE_CAPACITY_SIZE );
        /// <summary>
        /// 等待需要发出的数据锁
        /// </summary>
        private SpinLock m_LockFlushAndPending = new SpinLock();
        #endregion

        #region zh-CHS 属性 | en Properties
        /// <summary>
        /// 当前需发送的数据是否空的
        /// </summary>
        public bool IsEmpty
        {
            get { return ( m_PendingBuffer.Count <= 0 && m_FlushBuffer.IsNull == true  ); }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_WaitSendSize = 0;
        #endregion
        /// <summary>
        /// 缓冲区内还有多少没有发送的数据
        /// </summary>
        public long WaitSendSize
        {
            get { return m_WaitSendSize; }
        }
        #endregion

        #region zh-CHS 静态属性 | en Static Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 缓冲的数据大小
        /// </summary>
        private static int s_CoalesceBufferSize = 512;
        #endregion
        /// <summary>
        /// 合并缓冲的数据大小
        /// </summary>
        public static int CoalesceBufferSize
        {
            get { return s_CoalesceBufferSize; }
            set
            {
                if ( s_CoalesceBufferSize == value )
                    return;

                if ( s_CoalesceBufferSize <= 0 )
                    return;

                s_CoalesceBufferSize = value;

                BufferPool tempBuffers = s_UnusedBuffers;
                s_UnusedBuffers = new BufferPool( "SendQueue - CoalescedBuffer", INITIAL_CAPACITY, s_CoalesceBufferSize );

                if ( tempBuffers != null )
                    tempBuffers.Free();
            }
        }
        #endregion

        #region zh-CHS 方法 | en Method
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 可能是windows操作系统的最大可发送的字节数
        /// </summary>
        private const int PENDING_MAX_BUFFER = 96 * 1024;
        #endregion
        /// <summary>
        /// 如果数据满了,且缓冲区内的数据是空的则返回需要发送的数据
        /// 调用Enqueue(...)后调用Dequeue(...),不能直接调用Dequeue(...)
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iOffset"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        public void Enqueue( byte[] byteBuffer, long iOffset, long iLength )
        {
            if ( byteBuffer == null )
                throw new Exception( "SendQueue.Enqueue(...) - byteBuffer == null error!" );

            if ( iOffset < 0 || iOffset >= byteBuffer.Length )
                throw new Exception( "SendQueue.Enqueue(...) - iOffset < 0 || iOffset >= byteBuffer.Length error!" );
            
            if ( iLength < 0 || iLength > byteBuffer.Length ) // 如果iLength == 0就返回空,如果iLength == 0就跳过
                throw new Exception( "SendQueue.Enqueue(...) - iLength < 0 || iLength > byteBuffer.Length error!" );
            
            if ( ( byteBuffer.Length - iOffset ) < iLength )
                throw new Exception( "SendQueue.Enqueue(...) - ( byteBuffer.Length - iOffset ) < iLength error!" );

            m_LockFlushAndPending.Enter();
            {
                do
                {
                    if ( m_FlushBuffer.IsNull == true )
                    {
                        // nothing yet buffered
                        m_FlushBuffer = SendBuffer.Instance();

                        if ( m_FlushBuffer.IsNull == true )
                            throw new Exception( "SendQueue.Enqueue(...) - m_FlushBuffer.IsNull == true error!" );
                    }

                    // 当前已经写入的字节
                    long iBytesWritten = m_FlushBuffer.Write( byteBuffer, iOffset, iLength );

                    iOffset += iBytesWritten;
                    iLength -= iBytesWritten;

                    // 写入需要发送的数据的大小
                    m_WaitSendSize += iBytesWritten;

                    // 如果数据没有满,且数据写入完毕则退出,返回空,不添加到集合内
                    if ( m_FlushBuffer.IsFull == true )
                    {
                        // 如果满了添加到集合内的尾处
                        m_PendingBuffer.Enqueue( m_FlushBuffer );
                        m_FlushBuffer = SendBuffer.NullBuffer; // 置空再次请求缓存
                    }
                } while ( iLength > 0 );
            }
            m_LockFlushAndPending.Exit();
        }

        /// <summary>
        /// 获取当前的数据
        /// </summary>
        /// <returns></returns>
        public SendBuffer Dequeue()
        {
            SendBuffer sendGram = SendBuffer.NullBuffer;

            m_LockFlushAndPending.Enter();
            {
                if ( m_PendingBuffer.Count > 0 )
                {
                    sendGram = m_PendingBuffer.Dequeue();   // 再给出数据
                }
                else if ( m_FlushBuffer.IsNull == false )
                {
                    sendGram = m_FlushBuffer;               // 再给出数据
                    m_FlushBuffer = SendBuffer.NullBuffer;
                }

                // 移去已发送的数据的大小
                m_WaitSendSize -= sendGram.Length;
            }
            m_LockFlushAndPending.Exit();

            return sendGram;
        }

        /// <summary>
        /// 清除数据
        /// </summary>
        public void Clear()
        {
            m_LockFlushAndPending.Enter();
            {
                while ( m_PendingBuffer.Count > 0 )
                    m_PendingBuffer.Dequeue().Release();

                if ( m_FlushBuffer.IsNull == false )
                {
                    m_FlushBuffer.Release();
                    m_FlushBuffer = SendBuffer.NullBuffer;
                }

                // 清空
                m_WaitSendSize = 0;
            }
            m_LockFlushAndPending.Exit();
        }
        #endregion

        #region zh-CHS 私有静态方法 | en Private Static Method
        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        #region zh-CHS 私有常量 | en Private Constants
        /// <summary>
        /// 
        /// </summary>
        private readonly static int INITIAL_CAPACITY = 1024;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        private static BufferPool s_UnusedBuffers = new BufferPool( "SendQueue - CoalescedBuffer", INITIAL_CAPACITY, s_CoalesceBufferSize );
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        internal static byte[] AcquireBuffer()
        {
            return s_UnusedBuffers.AcquireBuffer();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="byteBuffer"></param>
        internal static void ReleaseBuffer( byte[] byteBuffer )
        {
            Debug.Assert( byteBuffer != null, "SendQueue.ReleaseBuffer(...) - byteBuffer == null error!" );

            if ( byteBuffer.Length == s_CoalesceBufferSize ) // 可能修改过m_CoalesceBufferSize如果不同就抛弃它
                s_UnusedBuffers.ReleaseBuffer( byteBuffer );
        }
        #endregion
    }

内存池

   /// <summary>
    /// (内存池)难得用一次泛型,C# 比 C++ 泛型好用好写多了 :)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
    internal class MemoryPool<T> where T : new()
    {
        #region zh-CHS 共有的结构 | en Public Struct
        /// <summary>
        /// 
        /// </summary>
        public struct PoolInfo
        {
            #region zh-CHS 共有属性 | en Public Properties
            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private string m_strName;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public string Name
            {
                get { return m_strName; }
                internal set { m_strName = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private int m_iFreeCount;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public int FreeCount
            {
                get { return m_iFreeCount; }
                internal set { m_iFreeCount = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private int m_iInitialCapacity;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public int InitialCapacity
            {
                get { return m_iInitialCapacity; }
                internal set { m_iInitialCapacity = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private int m_iCurrentCapacity;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public int CurrentCapacity
            {
                get { return m_iCurrentCapacity; }
                internal set { m_iCurrentCapacity = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private int m_iMisses;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public int Misses
            {
                get { return m_iMisses; }
                internal set { m_iMisses = value; }
            }
            #endregion
        }
        #endregion

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 内存池的名字
        /// </summary>
        private string m_Name = string.Empty;
        /// <summary>
        /// 内存池的容量
        /// </summary>
        private int m_InitialCapacity = 0;
        /// <summary>
        /// 内存池的容量不足时再次请求数据的次数
        /// </summary>
        private int m_Misses = 0;
        /// <summary>
        /// 内存池
        /// </summary>
        private ConcurrentQueue<T> m_FreePool = new ConcurrentQueue<T>();
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 初始化内存池
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="iInitialCapacity"></param>
        public MemoryPool( string strName, int iInitialCapacity )
        {
            m_Name = strName;

            m_InitialCapacity = iInitialCapacity;

            for ( int iIndex = 0; iIndex < iInitialCapacity; ++iIndex )
                m_FreePool.Enqueue( new T() );
        }
        #endregion

        #region zh-CHS 共有方法 | en Public Methods
        /// <summary>
        /// 内存池请求数据
        /// </summary>
        /// <returns></returns>
        public T AcquirePoolContent()
        {
            T returnT = default( T );

            do
            {
                if ( m_FreePool.Count > 0 )
                {
                    if ( m_FreePool.TryDequeue( out returnT ) == true )
                        break;
                }

                ++m_Misses;

                for ( int iIndex = 0; iIndex < m_InitialCapacity; ++iIndex )
                    m_FreePool.Enqueue( new T() );

                if ( m_FreePool.TryDequeue( out returnT ) == true )
                    break;
            } while ( true );

            return returnT;
        }

        /// <summary>
        /// 内存池释放数据
        /// </summary>
        /// <param name="TContent"></param>
        public void ReleasePoolContent( T contentT )
        {
            if ( contentT == null )
                throw new ArgumentNullException( "TContent", "TContent == null" );

            m_FreePool.Enqueue( contentT );
        }

        /// <summary>
        /// 释放内存池内全部的数据
        /// </summary>
        public void Free()
        {
            m_FreePool = new ConcurrentQueue<T>();
        }

        /// <summary>
        /// 给出内存池的详细信息
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="iFreeCount"></param>
        /// <param name="iInitialCapacity"></param>
        /// <param name="iCurrentCapacity"></param>
        /// <param name="iMisses"></param>
        public MemoryPool<T>.PoolInfo GetPoolInfo()
        {
            MemoryPool<T>.PoolInfo poolInfo = new MemoryPool<T>.PoolInfo();

            // 可以不需要锁定的,因为只是给出没有修改数据
            poolInfo.Name = m_Name;
            poolInfo.FreeCount = m_FreePool.Count;
            poolInfo.InitialCapacity = m_InitialCapacity;
            poolInfo.CurrentCapacity = m_InitialCapacity * ( 1 + m_Misses ); // m_Misses是从零开始计算的因此需加1
            poolInfo.Misses = m_Misses;

            return poolInfo;
        }
        #endregion
    }

Byte的内存池

   /// <summary>
    /// Byte的内存池
    /// </summary>
    [MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
    public class BufferPool
    {
        #region zh-CHS 共有的结构 | en Public Struct
        /// <summary>
        /// 
        /// </summary>
        public struct PoolInfo
        {
            #region zh-CHS 共有属性 | en Public Properties
            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private string m_strName;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public string Name
            {
                get { return m_strName; }
                internal set { m_strName = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private long m_iBufferSize;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public long BufferSize
            {
                get { return m_iBufferSize; }
                internal set { m_iBufferSize = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private long m_iFreeCount;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public long FreeCount
            {
                get { return m_iFreeCount; }
                internal set { m_iFreeCount = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private long m_iInitialCapacity;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public long InitialCapacity
            {
                get { return m_iInitialCapacity; }
                internal set { m_iInitialCapacity = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private long m_iCurrentCapacity;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public long CurrentCapacity
            {
                get { return m_iCurrentCapacity; }
                internal set { m_iCurrentCapacity = value; }
            }

            #region zh-CHS 私有成员变量 | en Private Member Variables
            /// <summary>
            /// 
            /// </summary>
            private long m_iMisses;
            #endregion
            /// <summary>
            /// 
            /// </summary>
            public long Misses
            {
                get { return m_iMisses; }
                internal set { m_iMisses = value; }
            }
            #endregion
        }
        #endregion

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 内存池的名字
        /// </summary>
        private string m_BufferName;
        /// <summary>
        /// 数据获取的失败次数
        /// </summary>
        private long m_Misses;
        /// <summary>
        /// 数据的大小
        /// </summary>
        private long m_BufferSize;
        /// <summary>
        /// 初始的空间大小
        /// </summary>
        private long m_InitialCapacity;
        /// <summary>
        /// 内存池
        /// </summary>
        private ConcurrentQueue<byte[]> m_FreeBuffers = new ConcurrentQueue<byte[]>();
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 初始化构造
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="iInitialCapacity"></param>
        /// <param name="iBufferSize"></param>
        public BufferPool( string strBufferName, long iInitialCapacity, long iBufferSize )
        {
            m_BufferName = strBufferName;
            m_BufferSize = iBufferSize;
            m_InitialCapacity = iInitialCapacity;

            for ( int iIndex = 0; iIndex < iInitialCapacity; ++iIndex )
                m_FreeBuffers.Enqueue( new byte[iBufferSize] );

            s_Pools.Add( this );
        }
        #endregion

        #region zh-CHS 静态属性 | en Static Properties

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 存放全局Byte的内存列表
        /// </summary>
        private static SafeHashSet<BufferPool> s_Pools = new SafeHashSet<BufferPool>();
        #endregion
        /// <summary>
        /// 存放全局Byte的内存列表
        /// </summary>
        public static SafeHashSet<BufferPool> GlobalPools
        {
            get { return s_Pools; }
        }
        #endregion

        #region zh-CHS 方法 | en Method
        /// <summary>
        /// 内存池请求数据
        /// </summary>
        /// <returns></returns>
        public byte[] AcquireBuffer()
        {
            byte[] returnByteArray = null;

            do
            {
                if ( m_FreeBuffers.Count > 0 )
                {
                    if ( m_FreeBuffers.TryDequeue( out returnByteArray ) == true )
                        break;
                }

                ++m_Misses;

                for ( int iIndex = 0; iIndex < m_InitialCapacity; ++iIndex )
                    m_FreeBuffers.Enqueue( new byte[m_BufferSize] );

                if ( m_FreeBuffers.TryDequeue( out returnByteArray ) == true )
                    break;
            } while ( true );

            return returnByteArray;
        }

        /// <summary>
        /// 内存池请释放
        /// </summary>
        /// <param name="byteBuffer"></param>
        public void ReleaseBuffer( byte[] byteBuffer )
        {
            if ( byteBuffer == null )
                throw new ArgumentNullException( "byteBuffer", "BufferPool.ReleaseBuffer(...) - byteBuffer == null error!" );

            m_FreeBuffers.Enqueue( byteBuffer );
        }

        /// <summary>
        /// 从存放全局Byte的内存列表中删除自己,被回收内存
        /// </summary>
        public void Free()
        {
            s_Pools.Remove( this );
        }

        /// <summary>
        /// 获取内存池的详细信息
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="iFreeCount"></param>
        /// <param name="iInitialCapacity"></param>
        /// <param name="iCurrentCapacity"></param>
        /// <param name="iBufferSize"></param>
        /// <param name="iMisses"></param>
        public BufferPool.PoolInfo GetPoolInfo()
        {
            BufferPool.PoolInfo poolInfo = new BufferPool.PoolInfo();

            // 该可以不锁定的,因只是读取数据而已
            poolInfo.Name = m_BufferName;
            poolInfo.Misses = m_Misses;
            poolInfo.BufferSize = m_BufferSize;
            poolInfo.FreeCount = m_FreeBuffers.Count;
            poolInfo.InitialCapacity = m_InitialCapacity;
            poolInfo.CurrentCapacity = m_InitialCapacity * ( m_Misses + 1 );

            return poolInfo;
        }
        #endregion
    }

FIFOBuffer

 /// <summary>
    /// Implements FIFO(first in - first out) buffer.
    /// </summary>
    public class FifoBuffer
    {
        private object m_pLock       = new object();
        private byte[] m_pBuffer     = null;
        private int    m_ReadOffset  = 0;
        private int    m_WriteOffset = 0;

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="maxSize">Maximum number of bytes can buffer in FIFO.</param>
        /// <exception cref="ArgumentException">Is raised when </exception>
        public FifoBuffer(int maxSize)
        {
            if(maxSize < 1){
                throw new ArgumentException("Argument 'maxSize' value must be >= 1.");
            }

            m_pBuffer = new byte[maxSize];
        }


        #region method Read

        /// <summary>
        /// Reads up to specified count of bytes from the FIFO buffer.
        /// </summary>
        /// <param name="buffer">Buffer where to store data.</param>
        /// <param name="offset">Index in the buffer.</param>
        /// <param name="count">Maximum number of bytes to read.</param>
        /// <returns>Returns number of bytes readed. Returns 0 if no data in the buffer.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null reference.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Is raised when any of the arguments has out of allowed range.</exception>
        public int Read(byte[] buffer,int offset,int count)
        {
            if(buffer == null){
                throw new ArgumentNullException("buffer");
            }           
            if(offset < 0){
                throw new ArgumentOutOfRangeException("offset","Argument 'offset' value must be >= 0.");
            }
            if(count < 0){
                throw new ArgumentOutOfRangeException("count","Argument 'count' value must be >= 0.");
            }
            if(offset + count > buffer.Length){
                throw new ArgumentOutOfRangeException("count","Argument 'count' is bigger than than argument 'buffer' can store.");
            }

            lock(m_pLock){
                int countToRead = Math.Min(count,m_WriteOffset - m_ReadOffset);
                if(countToRead > 0){
                    Array.Copy(m_pBuffer,m_ReadOffset,buffer,offset,countToRead);
                    m_ReadOffset += countToRead;
                }

                return countToRead;
            }
        }

        #endregion

        #region method Write

        /// <summary>
        /// Writes specified number of bytes to the FIFO buffer.
        /// </summary>
        /// <param name="buffer">Data buffer.</param>
        /// <param name="offset">Index in the buffer.</param>
        /// <param name="count">Number of bytes to wrtite.</param>
        /// <param name="ignoreBufferFull">If true, disables excption raising when FIFO full.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null reference.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Is raised when any of the arguments has out of allowed range.</exception>
        /// <exception cref="DataSizeExceededException">Is raised when ignoreBufferFull = false and FIFO buffer has no room to store data.</exception>
        public void Write(byte[] buffer,int offset,int count,bool ignoreBufferFull)
        {
            if(buffer == null){
                throw new ArgumentNullException("buffer");
            }        
            if(offset < 0){
                throw new ArgumentOutOfRangeException("offset","Argument 'offset' value must be >= 0.");
            }
            if(count < 0 || (count + offset) > buffer.Length){
                throw new ArgumentOutOfRangeException("count");
            }

            lock(m_pLock){
                int freeSpace = m_pBuffer.Length - m_WriteOffset;

                // We don't have enough room to store data.
                if(freeSpace < count){
                    TrimStart();

                    // Recalculate free space.
                    freeSpace = m_pBuffer.Length - m_WriteOffset;

                    // After trim we can store data.
                    if(freeSpace >= count){
                        Array.Copy(buffer,offset,m_pBuffer,m_WriteOffset,count);
                        m_WriteOffset += count;
                    }
                    // We have not enough space.
                    else{
                        if(!ignoreBufferFull){
                            throw new DataSizeExceededException();
                        }
                    }
                }
                // Store data to buffer.
                else{
                    Array.Copy(buffer,offset,m_pBuffer,m_WriteOffset,count);
                    m_WriteOffset += count;
                }
            }
        }

        #endregion

        #region method Clear

        /// <summary>
        /// Clears buffer data.
        /// </summary>
        public void Clear()
        {
            lock(m_pLock){
                m_ReadOffset  = 0;
                m_WriteOffset = 0;
            }
        }

        #endregion


        #region method TrimStart

        /// <summary>
        /// Removes unused space from the buffer beginning.
        /// </summary>
        private void TrimStart()
        {            
            if(m_ReadOffset > 0){
                byte[] buffer = new byte[this.Available];
                Array.Copy(m_pBuffer,m_ReadOffset,buffer,0,buffer.Length);
                Array.Copy(buffer,m_pBuffer,buffer.Length);
                m_ReadOffset  = 0;
                m_WriteOffset = buffer.Length;
            }
        }

        #endregion


        #region Properties implementation

        /// <summary>
        /// Gets maximum number of bytes can buffer in FIFO.
        /// </summary>
        public int MaxSize
        {
            get{ return m_pBuffer.Length; }
        }

        /// <summary>
        /// Gets number of bytes avialable in FIFO.
        /// </summary>
        public int Available
        {
            get{ return m_WriteOffset - m_ReadOffset; }
        }

        #endregion
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rains卍Soft

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值