diff options
author | chai <215380520@qq.com> | 2023-10-14 12:06:40 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2023-10-14 12:06:40 +0800 |
commit | 949f5accd281a051e5e2eeb3df8767b4794b6a1e (patch) | |
tree | f3430190906a2f505274beaf9f0a04c44ce2c755 /Projects | |
parent | 528a2b59e1b5519ddf0bebff6e92300705656952 (diff) |
+ Message
Diffstat (limited to 'Projects')
-rw-r--r-- | Projects/Message/Message/Message.csproj | 13 | ||||
-rw-r--r-- | Projects/Message/Message/MessageReader.cs | 252 | ||||
-rw-r--r-- | Projects/Message/Message/MessageWriter.cs | 80 | ||||
-rw-r--r-- | Projects/Message/Message/MessageWriterTests.cs | 260 | ||||
-rw-r--r-- | Projects/Message/Message/Properties/Settings.Designer.cs | 26 | ||||
-rw-r--r-- | Projects/Message/Message/Properties/Settings.settings | 6 | ||||
-rw-r--r-- | Projects/Message/Message/UnitTest1.cs | 16 |
7 files changed, 500 insertions, 153 deletions
diff --git a/Projects/Message/Message/Message.csproj b/Projects/Message/Message/Message.csproj index f2f13d5..a15b051 100644 --- a/Projects/Message/Message/Message.csproj +++ b/Projects/Message/Message/Message.csproj @@ -26,7 +26,7 @@ <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> + <DefineConstants>TRACE;DEBUG;UNIT_TEST</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> @@ -54,12 +54,21 @@ <Compile Include="IRecyclable.cs" /> <Compile Include="MessageReader.cs" /> <Compile Include="MessageWriter.cs" /> + <Compile Include="MessageWriterTests.cs" /> <Compile Include="ObjectPool.cs" /> - <Compile Include="UnitTest1.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + <DependentUpon>Settings.settings</DependentUpon> + </Compile> </ItemGroup> <ItemGroup> <None Include="packages.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> </ItemGroup> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/Projects/Message/Message/MessageReader.cs b/Projects/Message/Message/MessageReader.cs index 7ec134b..b49f9e2 100644 --- a/Projects/Message/Message/MessageReader.cs +++ b/Projects/Message/Message/MessageReader.cs @@ -7,38 +7,63 @@ using System.Text; namespace MultiplayerToolkit { /// <summary> - /// + /// 可以处理嵌套消息的结构,和MessageWriter配对 /// </summary> public class MessageReader : IRecyclable { public static readonly ObjectPool<MessageReader> ReaderPool = new ObjectPool<MessageReader>(() => new MessageReader()); - public byte[] Buffer; // √ 缓冲区,会被子协议共享这个缓冲区 - public byte Tag; // √ 协议名 + public byte[] Buffer; // 缓冲区,会被子消息共享这个缓冲区 - public int Length; // √ 协议长度,对应的是MessageWriter里写入的2bytes包长度(不含length和tag) - public int Offset; // √ length和tag后面的位置(在Buffer中的位置),不是游标,不会随读取发生改变。会影响readHead的值 + // 消息长度,定值 + // * 如果是非根消息,对应的是MessageWriter里写入的2bytes包长度,即不含length的长度 + // * 如果是根消息,Length是整个有效数据在Buffer中的长度,包括Length + public int Length; - //数据位于Buffer中Offset索引开始Length长度,协议位于Buffer中Offset-3开始的Length+3长度 + // 有效数据偏移,定值,游标会在这个基础上偏移 + // * 如果是非根消息,Offset在Length后面的位置 + // * 如果是根消息,Offset等于0,表示有效数据在Buffer中的偏移 + public int Offset; public int BytesRemaining => this.Length - this.Position; - private MessageReader Parent; // 保存父协议索引,和父协议共享父协议的Buffer + public int TotalLength => this.Length + this.Offset; + + private MessageReader Parent; // 保存父消息索引,和父消息共享父消息的Buffer + + // 是否是根消息,根消息下面包含多个子消息,子消息可以嵌套重孙消息 + public bool IsRoot + { + get { return Parent == null; } + } + + // 子消息可读 + public bool IsReadable + { + get { return this.Parent != null; } + } public int Position { get { return this._position; } set { - this._position = value; // value是 + this._position = value; this.readHead = value + Offset; } } - private int _position; // √ 读取游标,相对于协议内容部分的偏移,从0开始,子协议也是从0开始,不是在Buffer中的索引 - private int readHead; // √ 读取游标,协议头部在Buffer中的位置,参考ReadMessage() + private int _position; // 读取游标,相对于消息内容部分的偏移,从0开始,子消息也是从0开始,不是在Buffer中的索引 + private int readHead; // 读取游标,消息头部在Buffer中的位置,参考ReadMessage() - public static MessageReader GetSized(int minSize) +#region 创建 + /// <summary> + /// 创建一个容量至少为minSize的空缓冲区 + /// </summary> + /// <param name="minSize"></param> + /// <param name="exactly"></param> + /// <returns></returns> + public static MessageReader GetSized(int minSize, bool exactly = false) { var output = ReaderPool.GetObject(); @@ -48,15 +73,25 @@ namespace MultiplayerToolkit } else { + if(exactly && output.Buffer.Length > minSize) + { + output.Buffer = new byte[minSize]; + } Array.Clear(output.Buffer, 0, output.Buffer.Length); } output.Offset = 0; + output.Length = 0; output.Position = 0; - output.Tag = byte.MaxValue; + output.Parent = null; return output; } + /// <summary> + /// 将缓冲区封装为根MessageReader,不拷贝 + /// </summary> + /// <param name="buffer"></param> + /// <returns></returns> public static MessageReader Get(byte[] buffer) { var output = ReaderPool.GetObject(); @@ -65,53 +100,60 @@ namespace MultiplayerToolkit output.Offset = 0; output.Position = 0; output.Length = buffer.Length; - output.Tag = byte.MaxValue; + output.Parent = null; return output; } /// <summary> - /// 创建一个新的父message,保存source。用于缓存message,因为source所在的原父message可能会被销毁,如果需要延迟处理消息,需要拷贝一份新的 + /// 拷贝buffer,封装为根MessageReader /// </summary> - /// <param name="source"></param> + /// <param name="buffer"></param> /// <returns></returns> - public static MessageReader CopyMessageIntoParent(MessageReader source) + public static MessageReader GetAndCopy(byte[] buffer) { - var output = MessageReader.GetSized(source.Length + 3); //3=2bytes(length) + 1byte(tag) - System.Buffer.BlockCopy(source.Buffer, source.Offset - 3, output.Buffer, 0, source.Length + 3); + var output = ReaderPool.GetObject(); + byte[] _buffer = new byte[buffer.Length]; + Array.Copy(buffer, _buffer, buffer.Length); + output.Buffer = _buffer; output.Offset = 0; output.Position = 0; - output.Length = source.Length + 3; + output.Length = _buffer.Length; + output.Parent = null; return output; } /// <summary> - /// 完全复制 一份 + /// 创建一个新的父message,保存source。用于缓存message,因为source所在的原父message可能会被销毁,如果需要延迟处理消息,需要拷贝一份新的 /// </summary> /// <param name="source"></param> /// <returns></returns> - public static MessageReader Get(MessageReader source) + public static MessageReader CopyMessageIntoParent(MessageReader source) { - var output = MessageReader.GetSized(source.Buffer.Length); - System.Buffer.BlockCopy(source.Buffer, 0, output.Buffer, 0, source.Buffer.Length); + var output = MessageReader.GetSized(source.Length + 2); //2=2bytes(length) + System.Buffer.BlockCopy(source.Buffer, source.Offset - 2, output.Buffer, 0, source.Length + 2); - output.Offset = source.Offset; - - output._position = source._position; - output.readHead = source.readHead; - - output.Length = source.Length; - output.Tag = source.Tag; + output.Offset = 0; + output.Position = 0; + output.Length = source.Length + 2; + output.Parent = null; return output; } - public static MessageReader Get(byte[] buffer, int offset) +#if UNIT_TEST + /// <summary> + /// 用于测试,引用buffer的一部分作为child message,后续可以直接读取 + /// </summary> + /// <param name="buffer"></param> + /// <param name="offset"></param> + /// <returns></returns> + public static MessageReader GetChildMessage(byte[] buffer, int offset) { - // Ensure there is at least a header - if (offset + 3 > buffer.Length) return null; + // 确保至少有一个length + if (offset + 2 > buffer.Length) return null; var output = ReaderPool.GetObject(); @@ -120,52 +162,54 @@ namespace MultiplayerToolkit output.Position = 0; output.Length = output.ReadUInt16(); // 读到的值为length - output.Tag = output.ReadByte(); - output.Offset += 3; + output.Offset += 2; output.Position = 0; + output.Parent = null; return output; } +#endif + +#endregion /// <summary> - /// Produces a MessageReader using the parent's buffer. This MessageReader should **NOT** be recycled. + /// 返回一个可读子消息,引用了父缓冲区,**不要回收** /// </summary> public MessageReader ReadMessage() { - // Ensure there is at least a header - if (this.BytesRemaining < 3) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}"); + // 至少有一个length + if (this.BytesRemaining < 2) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}"); MessageReader output = new MessageReader(); output.Parent = this; output.Buffer = this.Buffer; - output.Offset = this.readHead; // 下面会读取 + output.Offset = this.readHead; output.Position = 0; - // 读length和tag的值并保存在字段里 - output.Length = output.ReadUInt16(); - output.Tag = output.ReadByte(); + output.Length = output.ReadUInt16(); // length - // Offset, readHead齐步走,移到Length和Tag后面,_position=0 - output.Offset += 3; // 3=length+tag + output.Offset += 2; // 2=length output.Position = 0; - if (this.BytesRemaining < output.Length + 3) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {output.Length + 3} of {this.BytesRemaining}"); + // 数据不全 + if (this.BytesRemaining < output.Length + 2) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {output.Length + 2} of {this.BytesRemaining}"); - this.Position += output.Length + 3; //跳过整个子协议 + this.Position += output.Length + 2; //跳过整个子消息 return output; } +#if UNIT_TEST /// <summary> - /// Produces a MessageReader with a new buffer. This MessageReader should be recycled. + /// 仅用于测试,返回一个可读子消息,并且拷贝数据,可回收 + /// Offset为0,开头没有Length数据 /// </summary> public MessageReader ReadMessageAsNewBuffer() { - if (this.BytesRemaining < 3) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}"); + if (this.BytesRemaining < 2) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}"); - var len = this.ReadUInt16(); - var tag = this.ReadByte(); + var len = this.ReadUInt16(); // Position += 2 if (this.BytesRemaining < len) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {len} of {this.BytesRemaining}"); @@ -174,19 +218,14 @@ namespace MultiplayerToolkit Array.Copy(this.Buffer, this.readHead, output.Buffer, 0, len); output.Length = len; - output.Tag = tag; + //output.Tag = tag; this.Position += output.Length; return output; } +#endif - public MessageWriter StartWriter() - { - var output = new MessageWriter(this.Buffer); - output.Position = this.readHead; - return output; - } - +#if UNIT_TEST public MessageReader Duplicate() { var output = GetSized(this.Length); @@ -200,60 +239,65 @@ namespace MultiplayerToolkit public void RemoveMessage(MessageReader reader) { - var temp = MessageReader.GetSized(reader.Buffer.Length); + MessageReader temp = null; try { - var headerOffset = reader.Offset - 3; - var endOfMessage = reader.Offset + reader.Length; - var len = reader.Buffer.Length - endOfMessage; + var headerOffset = reader.Offset - 2; + var endOfMessage = reader.Offset + reader.Length; // 有效部分的后一个byte + var len = this.TotalLength - endOfMessage; + temp = MessageReader.GetSized(len); Array.Copy(reader.Buffer, endOfMessage, temp.Buffer, 0, len); Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset, len); - this.AdjustLength(reader.Offset, reader.Length + 3); + this.AdjustLength(reader.Offset, reader.Length + 2); } finally { - temp.Recycle(); + if(temp != null) + { + temp.Recycle(); + } } } - //public void InsertMessage(MessageReader reader, MessageWriter writer) - //{ - // var temp = MessageReader.GetSized(reader.Buffer.Length); - // try - // { - // var headerOffset = reader.Offset - 3; - // var startOfMessage = reader.Offset; - // var len = reader.Buffer.Length - startOfMessage; - // int writerOffset = 3; - // switch (writer.SendOption) - // { - // case SendOption.Reliable: - // writerOffset = 3; - // break; - // case SendOption.None: - // writerOffset = 1; - // break; - // } - - // //store the original buffer in temp - // Array.Copy(reader.Buffer, headerOffset, temp.Buffer, 0, len); - - // //put the contents of writer in at headerOffset - // Array.Copy(writer.Buffer, writerOffset, this.Buffer, headerOffset, writer.Length - writerOffset); - - // //put the original buffer in after that - // Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset + (writer.Length - writerOffset), len - writer.Length); - - // this.AdjustLength(-1 * reader.Offset, -1 * (writer.Length - writerOffset)); - // } - // finally - // { - // temp.Recycle(); - // } - //} + /// <summary> + /// 在reader前面插入一条消息 + /// </summary> + /// <param name="reader">父reader</param> + /// <param name="writer"></param> + public void InsertMessage(MessageReader reader, MessageWriter writer) + { + var temp = MessageReader.GetSized(reader.Buffer.Length); + try + { + var headerOffset = reader.Offset - 3; // headerOffset是length+tag,这个方法仅仅接受reader不含sendoption的情况 + var startOfMessage = reader.Offset; // 头部后面的数据开始的索引 + var len = reader.Buffer.Length - headerOffset; // 疑似写错了,应该是headerOffset + int writerOffset = 0; + + //store the original buffer in temp + Array.Copy(reader.Buffer, headerOffset, temp.Buffer, 0, len); + + //put the contents of writer in at headerOffset + Array.Copy(writer.Buffer, writerOffset, this.Buffer, headerOffset, writer.Length - writerOffset); + + //put the original buffer in after that + Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset + (writer.Length - writerOffset), len - writer.Length); + + this.AdjustLength(-1 * reader.Offset, -1 * (writer.Length - writerOffset)); + } + finally + { + temp.Recycle(); + } + } + /// <summary> + /// 递归调整length值 + /// </summary> + /// <param name="offset">子消息的Offset值</param> + /// <param name="amount">子消息总长度,含length</param> private void AdjustLength(int offset, int amount) { if (this.readHead > offset) @@ -263,7 +307,7 @@ namespace MultiplayerToolkit if (Parent != null) { - var lengthOffset = this.Offset - 3; + var lengthOffset = this.Offset - 2; var curLen = this.Buffer[lengthOffset] | (this.Buffer[lengthOffset + 1] << 8); @@ -271,19 +315,21 @@ namespace MultiplayerToolkit this.Length -= amount; this.Buffer[lengthOffset] = (byte)curLen; - this.Buffer[lengthOffset + 1] = (byte)(this.Buffer[lengthOffset + 1] >> 8); + this.Buffer[lengthOffset + 1] = (byte)(curLen >> 8); Parent.AdjustLength(offset, amount); } } +#endif + public void Recycle() { this.Parent = null; ReaderPool.PutObject(this); } - #region Read Methods +#region Read Methods public bool ReadBoolean() { byte val = this.FastByte(); @@ -444,7 +490,7 @@ namespace MultiplayerToolkit return output; } - #endregion +#endregion [MethodImpl(MethodImplOptions.AggressiveInlining)] private byte FastByte() diff --git a/Projects/Message/Message/MessageWriter.cs b/Projects/Message/Message/MessageWriter.cs index 7646135..845a901 100644 --- a/Projects/Message/Message/MessageWriter.cs +++ b/Projects/Message/Message/MessageWriter.cs @@ -10,48 +10,42 @@ namespace MultiplayerToolkit /// AmongUsùȥ˰ͷش /// ṹ /// ------------------------------------- - /// 2bytes (ushort)Эijȣ2bytes - /// ------------------------------------- - /// 1byte ЭͣЭ0ԶЭ1 - /// (2byte) (ԶЭ飬ṩһmodţSteam.UGC.Itemidulong 8bytesеţ֧65535mod) - /// 2byte (ushort)ЭID 0-65535 + /// 2bytes (ushort)Ϣijȣ2bytes + /// (------------------------------------- + /// 1byte ϢͣϢ0ԶϢ1 + /// (2byte) (ԶϢṩһmodţSteam.UGC.Itemidulong 8bytesеţ֧65535mod) + /// 2byte (ushort)ϢID 0-65535 /// - /// ------------------------------------- + /// -------------------------------------) /// </summary> public class MessageWriter : IRecyclable { public const int BYTE_COUNT_OF_LENGTH = 2; // ռ2 bytes - public static int BufferSize = 64000; // Э֧64000ֽڣ62.5KB - public static readonly ObjectPool<MessageWriter> WriterPool = new ObjectPool<MessageWriter>(() => new MessageWriter(BufferSize)); + public static int BUFFER_SIZE = 64000; // Ϣ֧64000ֽڣ62.5KB + public static readonly ObjectPool<MessageWriter> WriterPool = new ObjectPool<MessageWriter>(() => new MessageWriter(BUFFER_SIZE)); public byte[] Buffer; - public int Length; // ЧbufferеijȣܰǶЭ - public int Position; // дλ - - // lengthһڻĴСLengthһÿЭЭݲֵֽ + public int Length; // ЧbufferеijȣܰǶϢ + public int Position; // дα - private Stack<int> messageStarts = new Stack<int>(); // ¼ЭbufferеʼλãǶṹ + // lengthһڻĴСLengthһÿϢϢݲֵֽ - public MessageWriter(byte[] buffer) - { - this.Buffer = buffer; - this.Length = this.Buffer.Length; - } + private Stack<int> messageStarts = new Stack<int>(); // ¼ϢbufferеʼλãǶṹ - /// +#region + /// <summary> + /// һΪָСMessage + /// </summary> + /// <param name="bufferSize"></param> public MessageWriter(int bufferSize) { this.Buffer = new byte[bufferSize]; } - public byte[] ToByteArray() - { - byte[] output = new byte[this.Length]; - System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length); - return output; - } - - /// <param name="sendOption">The option specifying how the message should be sent.</param> + /// <summary> + /// ӳһСΪBufferSizeMessage + /// </summary> + /// <returns></returns> public static MessageWriter Get() { MessageWriter output = WriterPool.GetObject(); @@ -59,6 +53,14 @@ namespace MultiplayerToolkit return output; } +#endregion + + public byte[] ToByteArray() + { + byte[] output = new byte[this.Length]; + System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length); + return output; + } /// <summary> /// Ƿexpectedȵ @@ -70,7 +72,14 @@ namespace MultiplayerToolkit return this.Length >= expected; } - /// + public bool HasBytesExactly(int exact) + { + return this.Length == exact; + } + + /// <summary> + /// ʼдϢд2bytesΪ + /// </summary> public void StartMessage() { var messageStart = this.Position; @@ -78,9 +87,12 @@ namespace MultiplayerToolkit this.Buffer[messageStart] = 0; // length this.Buffer[messageStart + 1] = 0; // length this.Position += 2; // ushort length + this.Length = this.Position; } - /// + /// <summary> + /// ôϢȣ־Ϣ + /// </summary> public void EndMessage() { var lastMessageStart = messageStarts.Pop(); @@ -117,18 +129,22 @@ namespace MultiplayerToolkit #region WriteMethods + /// <summary> + /// дȡϢͨڷܵϢĹ㲥תҪStart\End + /// </summary> + /// <param name="target"></param> public void CopyFrom(MessageReader target) { int offset, length; - if (target.Tag == byte.MaxValue) + if (target.IsRoot) { offset = target.Offset; length = target.Length; } else { - offset = target.Offset - 3; - length = target.Length + 3; + offset = target.Offset - 2; + length = target.Length + 2; } System.Buffer.BlockCopy(target.Buffer, offset, this.Buffer, this.Position, length); diff --git a/Projects/Message/Message/MessageWriterTests.cs b/Projects/Message/Message/MessageWriterTests.cs new file mode 100644 index 0000000..9a873a5 --- /dev/null +++ b/Projects/Message/Message/MessageWriterTests.cs @@ -0,0 +1,260 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + + +namespace MultiplayerToolkit +{ + + [TestClass] + public class MessageWriterTests + { + + [TestMethod] + public void HasBytesExactly() + { + var msg = new MessageWriter(128); + + msg.StartMessage(); + Assert.IsTrue(msg.HasBytesExactly(2)); + msg.Write((int)32); + Assert.IsTrue(msg.HasBytesExactly(6)); + msg.EndMessage(); + + msg.StartMessage(); + Assert.IsTrue(msg.HasBytesExactly(8)); + msg.Write((short)2); + Assert.IsTrue(msg.HasBytesExactly(10)); + msg.EndMessage(); + Assert.IsTrue(msg.HasBytesExactly(10)); + } + + [TestMethod] + public void HasBytesExactlyNest() + { + var msg = new MessageWriter(128); + + msg.StartMessage(); + Assert.IsTrue(msg.HasBytesExactly(2)); + msg.Write((int)32); + Assert.IsTrue(msg.HasBytesExactly(6)); + //msg.EndMessage(); + + msg.StartMessage(); + Assert.IsTrue(msg.HasBytesExactly(8)); + msg.Write((short)2); + Assert.IsTrue(msg.HasBytesExactly(10)); + msg.EndMessage(); + msg.EndMessage(); + Assert.IsTrue(msg.HasBytesExactly(10)); + } + + [TestMethod] + public void HasBytesExactlyGet() + { + var msg = MessageWriter.Get(); + + msg.StartMessage(); + Assert.IsTrue(msg.HasBytesExactly(2)); + msg.Write((int)32); + Assert.IsTrue(msg.HasBytesExactly(6)); + msg.EndMessage(); + + msg.StartMessage(); + Assert.IsTrue(msg.HasBytesExactly(8)); + msg.Write((short)2); + Assert.IsTrue(msg.HasBytesExactly(10)); + msg.EndMessage(); + Assert.IsTrue(msg.HasBytesExactly(10)); + } + + [TestMethod] + public void CancelMessages() + { + var msg = new MessageWriter(128); + + msg.StartMessage(); + msg.Write(32); + + msg.StartMessage(); + msg.Write(2); + msg.CancelMessage(); + + Assert.AreEqual(6, msg.Length); + Assert.IsTrue(msg.HasBytes(6)); + + msg.CancelMessage(); + + Assert.AreEqual(0, msg.Length); + Assert.IsFalse(msg.HasBytes(1)); + } + + + [TestMethod] + public void WriteProperInt() + { + const int Test1 = int.MaxValue; + const int Test2 = int.MinValue; + + var msg = new MessageWriter(128); + msg.Write(Test1); + msg.Write(Test2); + + Assert.AreEqual(8, msg.Length); + Assert.AreEqual(msg.Length, msg.Position); + + using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length)) + using (BinaryReader reader = new BinaryReader(m)) + { + Assert.AreEqual(Test1, reader.ReadInt32()); + Assert.AreEqual(Test2, reader.ReadInt32()); + } + } + + [TestMethod] + public void WriteProperBool() + { + const bool Test1 = true; + const bool Test2 = false; + + var msg = new MessageWriter(128); + msg.Write(Test1); + msg.Write(Test2); + + Assert.AreEqual(2, msg.Length); + Assert.AreEqual(msg.Length, msg.Position); + + using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length)) + using (BinaryReader reader = new BinaryReader(m)) + { + Assert.AreEqual(Test1, reader.ReadBoolean()); + Assert.AreEqual(Test2, reader.ReadBoolean()); + } + } + + [TestMethod] + public void WriteProperString() + { + const string Test1 = "Hello"; + string Test2 = new string(' ', 1024); + var msg = new MessageWriter(2048); + msg.Write(Test1); + msg.Write(Test2); + msg.Write(string.Empty); + + Assert.AreEqual(msg.Length, msg.Position); + + using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length)) + using (BinaryReader reader = new BinaryReader(m)) + { + Assert.AreEqual(Test1, reader.ReadString()); + Assert.AreEqual(Test2, reader.ReadString()); + Assert.AreEqual(string.Empty, reader.ReadString()); + } + } + + [TestMethod] + public void WriteProperFloat() + { + const float Test1 = 12.34f; + + var msg = new MessageWriter(2048); + msg.Write(Test1); + + Assert.AreEqual(msg.Length, msg.Position); + + using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length)) + using (BinaryReader reader = new BinaryReader(m)) + { + Assert.AreEqual(Test1, reader.ReadSingle()); + } + } + + [TestMethod] + public void WritePackedUint() + { + var msg = new MessageWriter(2048); + msg.StartMessage(); + msg.WritePacked(8u); + msg.WritePacked(250u); + msg.WritePacked(68000u); + msg.EndMessage(); + + Assert.AreEqual(2 + 1 + 2 + 3, msg.Position); + Assert.AreEqual(msg.Length, msg.Position); + + MessageReader reader = MessageReader.GetChildMessage(msg.Buffer, 0); + + Assert.AreEqual(8u, reader.ReadPackedUInt32()); + Assert.AreEqual(250u, reader.ReadPackedUInt32()); + Assert.AreEqual(68000u, reader.ReadPackedUInt32()); + } + + [TestMethod] + public void WritePackedInt() + { + var msg = new MessageWriter(2048); + msg.StartMessage(); + msg.WritePacked(8); + msg.WritePacked(250); + msg.WritePacked(68000); + msg.WritePacked(60168000); + msg.WritePacked(-68000); + msg.WritePacked(-250); + msg.WritePacked(-8); + + msg.WritePacked(0); + msg.WritePacked(-1); + msg.WritePacked(int.MinValue); + msg.WritePacked(int.MaxValue); + msg.EndMessage(); + + Assert.AreEqual(2 + 1 + 2 + 3 + 4 + 5 + 5 + 5 + 1 + 5 + 5 + 5, msg.Position); + Assert.AreEqual(msg.Length, msg.Position); + + MessageReader reader = MessageReader.GetChildMessage(msg.Buffer, 0); + + Assert.AreEqual(8, reader.ReadPackedInt32()); + Assert.AreEqual(250, reader.ReadPackedInt32()); + Assert.AreEqual(68000, reader.ReadPackedInt32()); + Assert.AreEqual(60168000, reader.ReadPackedInt32()); + + Assert.AreEqual(-68000, reader.ReadPackedInt32()); + Assert.AreEqual(-250, reader.ReadPackedInt32()); + Assert.AreEqual(-8, reader.ReadPackedInt32()); + + Assert.AreEqual(0, reader.ReadPackedInt32()); + Assert.AreEqual(-1, reader.ReadPackedInt32()); + Assert.AreEqual(int.MinValue, reader.ReadPackedInt32()); + Assert.AreEqual(int.MaxValue, reader.ReadPackedInt32()); + } + + [TestMethod] + public void WritesMessageLength() + { + var msg = new MessageWriter(2048); + msg.StartMessage(); + msg.Write(65534); + msg.EndMessage(); + + Assert.AreEqual(2 + 4, msg.Position); + Assert.AreEqual(msg.Length, msg.Position); + + using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length)) + using (BinaryReader reader = new BinaryReader(m)) + { + Assert.AreEqual(4, reader.ReadUInt16()); // Length After Type and Target + Assert.AreEqual(65534, reader.ReadInt32()); // Content + } + } + + [TestMethod] + public void GetLittleEndian() + { + Assert.IsTrue(MessageWriter.IsLittleEndian()); + } + + } +}
\ No newline at end of file diff --git a/Projects/Message/Message/Properties/Settings.Designer.cs b/Projects/Message/Message/Properties/Settings.Designer.cs new file mode 100644 index 0000000..47da87d --- /dev/null +++ b/Projects/Message/Message/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Message.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Projects/Message/Message/Properties/Settings.settings b/Projects/Message/Message/Properties/Settings.settings new file mode 100644 index 0000000..049245f --- /dev/null +++ b/Projects/Message/Message/Properties/Settings.settings @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> +</SettingsFile> diff --git a/Projects/Message/Message/UnitTest1.cs b/Projects/Message/Message/UnitTest1.cs deleted file mode 100644 index 2e02c6e..0000000 --- a/Projects/Message/Message/UnitTest1.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; - -namespace Message -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestMethod1() - { - - Assert.AreEqual(1, 1); - } - } -} |