# C# TCP粘包缓存

  • 减少了ToArray() 的复制操作(包已完整,获取包数据时)
  • 减少了GetRange() 的复制操作(当需要获取到头部4字节判断包长度时)

代码

C#
public class ReceiveDataBuffer
{
    private Memory<byte> items { get; set; } = Helper.EmptyArray.AsMemory();
    private int size = 0;
    public int Size
    {
        get
        {
            return size;
        }
        private set
        {
            if (value == 0)
            {
                items = Helper.EmptyArray;
            }
            else if (value > items.Length)
            {
                Memory<byte> newItems = new byte[value].AsMemory();
                items.CopyTo(newItems);
                items = newItems;
            }
        }
    }

    public Memory<byte> Data
    {
        get
        {
            return items;
        }
    }

    public void AddRange(Memory<byte> data, int length)
    {
        BeResize(length);

        data.Slice(0, length).CopyTo(items.Slice(size, length));
        size += length;
    }

    public void AddRange(byte[] data, int offset, int length)
    {
        BeResize(length);
        data.AsMemory(offset, length).CopyTo(items.Slice(size, length));
        size += length;
    }

    public void RemoveRange(int index, int count)
    {
        if (index >= 0 && count > 0 && size - index >= count)
        {
            size -= count;
            if (index < size)
            {
                items.Slice(index + count, size - index).CopyTo(items.Slice(index, size - index));
            }
        }
    }

    public void Clear(bool clearData = false)
    {
        size = 0;
        if (clearData)
        {
            Size = 0;
        }
    }

    private void BeResize(int length)
    {
        int _size = size + length;
        if (_size > items.Length)
        {
            int newsize = items.Length * 2;
            if (newsize < _size)
            {
                newsize = _size;
            }
            Size = newsize;
        }
    }
}

使用示例

C#
ReceiveDataBuffer buffer = new ReceiveDataBuffer();
byte[] bytes = new byte[8*1024];
while(true)
{

    //从网络接收到数据
    int length =  socket.ReceiveAsync(bytes);
    if (length == 0)
    {
        break;
    }

    //将网络数据添加到缓存中
    buffer.AddRange(bytes, length);
    do
    {
        //0-4字节是包长度内容
        int packageLen = BitConverter.ToInt32(buffer.Data.Span);
        if (packageLen > buffer.Size - 4)
        {
            break;
        }
        
        Memory<byte> data = buffer.Data.Slice(4, packageLen);
        //拿data去随便干啥

       
        //删除已使用的数据
        buffer.RemoveRange(0, packageLen + 4);

    } while (buffer.Size > 4);
}