前面其实除了我们使用protobuf来使用作为传输消息的内容外,我们之前读取消息已经接收消息都没有一个准备的类来帮助我们处理消息,这个类的作用就是来帮助我们收发消息以及后面我们要用的消息的编码和消息的解码使用的.
看一下前面的代码我们接收到服务器消息的时候都是简单粗暴的new出一个byte[]字节数组来接收服务器发送过来的数据,这样不方便大型项目的后期管理和维护,设计模式中也讲到类的单一职责嘛,那么我们现在就准备一个类专门类负责数据的收发内容.
using System;
public class ByteArray
{
/// <summary>
/// 默认大小
/// </summary>
private const int DEFAULT_SIZE = 1024;
/// <summary>
/// 初始大小
/// </summary>
private int initSize = 0;
/// <summary>
/// 缓冲区
/// </summary>
public byte[] bytes;
/// <summary>
/// 读取位置
/// </summary>
/// <returns></returns>
public int readInx = 0;
/// <summary>
/// 写入的位置
/// </summary>
public int writeInx = 0;
/// <summary>
/// 容量
/// </summary>
public int capacity = 0;
/// <summary>
/// 剩余空间
/// </summary>
public int remain
{
get { return capacity - writeInx; }
}
/// <summary>
/// 数据长度
/// </summary>
public int Length
{
get { return writeInx - readInx; }
}
public ByteArray(byte[] defaultBytes)
{
bytes = defaultBytes;
capacity = defaultBytes.Length;
initSize = defaultBytes.Length;
readInx = 0;
writeInx = defaultBytes.Length;
}
public ByteArray(int size = DEFAULT_SIZE)
{
bytes = new byte[size];
capacity = size;
initSize = size;
readInx = 0;
writeInx = 0;
}
/// <summary>
/// 动态扩容
/// </summary>
/// <param name="size">所需要的数据长度</param>
public void ReSize(int size)
{
if (size < Length) return;
if (size < initSize) return;
int n = 1;
while (n < size)
{
n *= 2;
}
capacity = n;
byte[] newBytes = new byte[capacity];
Array.Copy(bytes, readInx, newBytes, 0, writeInx - readInx);
bytes = newBytes;
writeInx = Length;
readInx = 0;
}
/// <summary>
/// 检查并移动数据
/// </summary>
public void CheckAndMoveBytes()
{
if (Length < 8)
{
MoveBytes();
}
}
/// <summary>
/// 具体的移动数据
/// </summary>
public void MoveBytes()
{
//原数组,源数组的起始位置,目标数组,目标数组的起始位置,要复制的消息长度
Array.Copy(bytes, readInx, bytes, 0, Length);
writeInx = Length;
readInx = 0;
}
/// <summary>
/// 写入数据
/// </summary>
/// <param name="bs"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <returns></returns>
public int Write(byte[] bs, int offset, int count)
{
if (remain < count)
{
ReSize(Length + count);
}
Array.Copy(bs, offset, bytes, writeInx, count);
writeInx += count;
return count;
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="bs"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <returns></returns>
public int Read(byte[] bs, int offset, int count)
{
count = Math.Min(count, Length);
Array.Copy(bytes, readInx, bs, offset, count);
readInx += count;
CheckAndMoveBytes();
return count;
}
/// <summary>
/// 读取Int16
/// </summary>
/// <returns></returns>
public Int16 ReadInt16()
{
if (Length < 2) return 0;
Int16 ret = (Int16) ((bytes[1] << 8) | bytes[0]);
readInx += 2;
CheckAndMoveBytes();
return ret;
}
/// <summary>
/// 读取Int32
/// </summary>
/// <returns></returns>
public Int32 ReadInt32()
{
if (Length < 4) return 0;
Int32 ret = (Int32) ((bytes[3] << 24) |
(bytes[2] << 16) |
(bytes[1] << 8) |
bytes[0]);
readInx += 4;
CheckAndMoveBytes();
return ret;
}
/// <summary>
/// 打印缓冲区(仅为调试)
/// </summary>
/// <returns></returns>
public override string ToString()
{
return BitConverter.ToString(bytes, readInx, Length);
}
/// <summary>
/// 打印调试信息(仅为调试)
/// </summary>
/// <returns></returns>
public string Debug()
{
return string.Format("readIdx({0}) writeIdx({1}) bytes({2})", readInx, writeInx,
BitConverter.ToString(bytes, 0, bytes.Length));
}
}