using System; using System.Collections.Generic; using System.Text; using System.IO; namespace Xse { namespace Protocol { public interface IPacket { byte[] ToArray(); } public interface IBinaryData { void write(BinaryPacketWriter w); bool read(BinaryPacketReader r); } public class BinaryPacketWriter : BinaryWriter { Encoding myEncoding = Encoding.UTF8; public Encoding Encoding { get { return myEncoding; } set { myEncoding = value; } } public int Left { get { return (int)(BaseStream.Length - BaseStream.Position); } } public BinaryPacketWriter(Stream s) : base(s) { } public BinaryPacketWriter(Stream s, Encoding encoding) : base(s) { myEncoding = encoding; } public void WriteTinyString(string val) { byte[] ary = Encoding.GetBytes(val); byte len = (byte)ary.Length; Write(len); Write(ary, 0, len); } public void WriteMediumString(string val) { byte[] ary = Encoding.GetBytes(val); UInt16 len = (UInt16)ary.Length; Write(len); Write(ary, 0, len); } public void WriteLongString(string val) { byte[] ary = Encoding.GetBytes(val); int len = ary.Length; Write(len); Write(ary, 0, len); } public void WriteString(string val) { byte[] ary = Encoding.GetBytes(val); Write(ary, 0, ary.Length); } } public class BinaryPacketReader : BinaryReader { Encoding myEncoding = Encoding.UTF8; public Encoding Encoding { get { return myEncoding; } set { myEncoding = value; } } public int Left { get { return (int)(BaseStream.Length - BaseStream.Position); } } public BinaryPacketReader(Stream s) : base(s) { } public BinaryPacketReader(Stream s, Encoding encoding) : base(s) { myEncoding = encoding; } public string ReadTinyString() { byte len = this.ReadByte(); byte[] ary = this.ReadBytes(len); return myEncoding.GetString(ary); } public string ReadMediumString() { UInt16 len = this.ReadUInt16(); byte[] ary = this.ReadBytes(len); return myEncoding.GetString(ary); } public string ReadLongString() { int len = this.ReadInt32(); byte[] ary = this.ReadBytes(len); return myEncoding.GetString(ary); } public string ReadLeftAsString() { int len = (int)(BaseStream.Length - BaseStream.Position); byte[] ary = this.ReadBytes(len); return myEncoding.GetString(ary); } public string ReadString(int size) { byte[] ary = this.ReadBytes(size); int pos = Array.IndexOf<byte>(ary, 0); if (pos < 0) pos = size; return myEncoding.GetString(ary, 0, pos); } } public class BinaryPacket : IDisposable, IPacket { byte[] myArray = null; MemoryStream myDataStream = null; public MemoryStream DataStream { get { return myDataStream; } } BinaryPacketReader myReader = null; BinaryPacketWriter myWriter = null; public BinaryPacketWriter Writer { get { if (myWriter == null)myWriter = new BinaryPacketWriter(DataStream); return myWriter; } } public BinaryPacketReader Reader { get { if (myReader == null)myReader = new BinaryPacketReader(DataStream); return myReader; } } #region IPacket 成员 public virtual byte[] ToArray() { //throw new NotImplementedException(); byte[] ary = new byte[myDataStream.Length]; myDataStream.Read(ary, 0, (int)myDataStream.Length); return ary; } #endregion public BinaryPacket(byte[] data) { myArray = data; myDataStream = new MemoryStream(myArray); } public BinaryPacket(byte[] data, int ofs, int len) { myArray = data; myDataStream = new MemoryStream(myArray, ofs, len); } #region IDisposable 成员 public void Dispose() { myDataStream = null; myArray = null; } #endregion } public class SimpleBinaryPacket : IDisposable, IPacket { public const int HEADER_SIZE = sizeof(ushort) * 2; byte[] myArray = null; MemoryStream myDataStream = null; UInt16 myCommand = 0; public UInt16 Command { get { return myCommand; } } public MemoryStream DataStream { get { return myDataStream; } } BinaryPacketReader myReader = null; BinaryPacketWriter myWriter = null; public BinaryPacketWriter Writer { get { if (myWriter == null)myWriter = new BinaryPacketWriter(DataStream); return myWriter; } } public BinaryPacketReader Reader { get { if (myReader == null)myReader = new BinaryPacketReader(DataStream); return myReader; } } public int TotalLength { get { return sizeof(UInt16) * 2 + (int)DataStream.Length; } } public SimpleBinaryPacket(byte[] data, int ofs, int len) { myArray = data; if (len >= HEADER_SIZE) { myCommand = (UInt16)(((UInt16)data[ofs + 2]) | (((UInt16)data[ofs + 3]) << 8)); ofs += HEADER_SIZE; len -= HEADER_SIZE; } myDataStream = new MemoryStream(myArray, ofs, len); } public SimpleBinaryPacket(UInt16 cmd) { myCommand = cmd; myDataStream = new MemoryStream(); } internal void WriteTo(Stream s) { BinaryWriter br = new BinaryWriter(s); ushort len = (ushort)myDataStream.Length; br.Write(len); br.Write(Command); br.Write(myDataStream.GetBuffer(), 0, len); } public byte[] ToArray() { byte[] ary = new byte[HEADER_SIZE + myDataStream.Length]; MemoryStream ms = new MemoryStream(ary); WriteTo(ms); return ary; } #region IDisposable 成员 public void Dispose() { myDataStream = null; myArray = null; } #endregion } public delegate void OnPacketEventHandler(byte[] data, int ofs, int len); public class SimpleBinaryProtocolParser { const int HEADER_SIZE = 4; const int SIZEFIELD_SIZE = 2; const int MAX_CACHE_SIZE = 65539; byte[] myCacheArray = new byte[MAX_CACHE_SIZE + 1]; int myCacheLength = 0; int myCachePacketLength = 0; //public virtual void HandlePacket(byte[] data, int ofs, int len) { } public event OnPacketEventHandler OnPacket = null; int readPacketLength(byte[] data, int ofs) { return HEADER_SIZE + (int)(((UInt16)data[ofs]) | (((UInt16)data[ofs + 1]) << 8)); } public static ushort readCommand(byte[] data, int ofs) { return (ushort)(((ushort)data[ofs]) | (((ushort)data[ofs + 1]) << 8)); } bool writeCache(byte[] data, int ofs, int len) { if (myCacheLength + len > MAX_CACHE_SIZE) return false; Array.Copy(data, ofs, myCacheArray, myCacheLength, len); myCacheLength += len; if (myCachePacketLength == 0 && myCacheLength >= SIZEFIELD_SIZE) myCachePacketLength = readPacketLength(myCacheArray, 0); return true; } int readPacket(byte[] data, int ofs, int endofs) { int left = endofs - ofs; if (left < SIZEFIELD_SIZE) return ofs; int datalen = readPacketLength(data, ofs); if (left < datalen) return ofs; return (ofs + datalen); } int readPackets(byte[] data, int ofs, int endofs) { int ptr = readPacket(data, ofs, endofs); while (ptr > ofs) { if (OnPacket != null) OnPacket(data, ofs, ptr - ofs); //HandlePacket(data, ofs, ptr - ofs); ofs = ptr; ptr = readPacket(data, ofs, endofs); } return ptr; } public bool HandleData(byte[] data) { return HandleData(data, 0, data.Length); } public bool HandleData(byte[] data, int ofs, int len) { int endofdata = ofs + len; if (myCacheLength == 0) { int ptr = readPackets(data, ofs, endofdata); if (ptr < endofdata) { return writeCache(data, ptr, endofdata - ptr); } } else { int needlen = 0; if (myCachePacketLength == 0) { needlen = SIZEFIELD_SIZE - myCacheLength; if (needlen >= len) { return writeCache(data, ofs, len); } if (!writeCache(data, ofs, needlen)) return false; ofs += needlen; len -= needlen; } needlen = myCachePacketLength - myCacheLength; if (needlen > len) { return writeCache(data, ofs, len); } if (!writeCache(data, ofs, needlen)) return false; ofs += needlen; //len -= needlen; if (OnPacket != null) OnPacket(myCacheArray, 0, myCachePacketLength); myCacheLength = 0; myCachePacketLength = 0; if (ofs < endofdata) { ofs = readPackets(data, ofs, endofdata); if (ofs < endofdata) return writeCache(data, ofs, endofdata - ofs); } } return true; } } } }