示例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestConsole { class Program { static void Main(string[] args) { //封装协议包 ProtocolData pd = new ProtocolData(); pd.WriteUInt32(1001); pd.WriteUTF8String("Hello World!"); byte[] bytes = pd.EncapsulatePackage(); //解析协议包 PackageParser parser = new PackageParser(); parser.OnPackageComplete += OnPackageComplete; parser.Receive(bytes); Console.ReadKey(); } static void OnPackageComplete(ProtocolData pd) { Console.WriteLine("*** OnPackageComplete ***"); Console.WriteLine("id={0}, message={1}", pd.ID, pd.Message); } } } /// <summary> /// 数据包解析器 /// </summary> public class PackageParser { private ushort size = 0; private Stack<byte> receiveBuffer = new Stack<byte>(); public Action<ProtocolData> OnPackageComplete; public void Receive(byte[] bytes) { if (bytes == null || bytes.Length == 0) return; for (int i = bytes.Length-1; i >= 0; i--) receiveBuffer.Push(bytes[i]); Parse(); } private void Parse() { if (size == 0) { //用2个字节表示协议长度 if (receiveBuffer.Count < 2) return; //Peek() 返回顶部元素,但不删除 //Pop() 返回顶部元素,并删除 byte[] size_bytes = new byte[] { receiveBuffer.Pop(), receiveBuffer.Pop() }; size = BitConverter.ToUInt16(size_bytes, 0); } if (receiveBuffer.Count >= size) { //从缓冲区中提取出一个数据包 byte[] bytes = new byte[size]; for (int i = 0; i < size; i++) { bytes[i] = receiveBuffer.Pop(); } size = 0; if (OnPackageComplete != null) { ProtocolData p = new ProtocolData(bytes); OnPackageComplete(p); } } } } /// <summary> /// 协议数据 /// </summary> public class ProtocolData { //原始数据 private byte[] bytes; //协议ID private uint id; //消息 private string message; private List<byte> writeBuffer = new List<byte>(); public ProtocolData() { } public ProtocolData(byte[] bytes) { this.bytes = bytes; this.Parse(); } public uint ID { get { return id; } } public string Message { get { return message; } } private void Parse() { //从bytes中解析出具体字段 this.id = ReadUInt32(); this.message = ReadString(4);//跳过id } private uint ReadUInt32(int startIndex = 0) { uint i = BitConverter.ToUInt32(bytes, startIndex); return i; } private string ReadString(int startIndex = 0, int length = -1) { if (length == -1) length = bytes.Length - startIndex; //Copy byte[] bs = new byte[length]; for (int i = 0; i < length; i++) bs[i] = bytes[startIndex + i]; string s = System.Text.Encoding.UTF8.GetString(bs); return s; } public void WriteUInt32(uint i) { byte[] bytes = BitConverter.GetBytes(i); writeBuffer.AddRange(bytes); } public void WriteUTF8String(string s) { byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s); writeBuffer.AddRange(bytes); } // 封装协议包 public byte[] EncapsulatePackage() { //内容长度 ushort size = (ushort)writeBuffer.Count; List<byte> pb = new List<byte>(); pb.AddRange(BitConverter.GetBytes(size)); pb.AddRange(writeBuffer); return pb.ToArray(); } }
运行测试