From 01903c7e4451cc1ecd2dd0a3a4c71408a7b5f612 Mon Sep 17 00:00:00 2001 From: chai <215380520@qq.com> Date: Mon, 16 Oct 2023 11:32:53 +0800 Subject: + Packet --- Projects/Packet/Packet/.gitignore | 194 ++++++++++ .../Packet/Packet/MultiplayerToolkit/Packet.cs | 389 +++++++++++++++++++++ Projects/Packet/Packet/Packet.csproj | 69 ++++ Projects/Packet/Packet/Packet.sln | 25 ++ Projects/Packet/Packet/Properties/AssemblyInfo.cs | 20 ++ Projects/Packet/Packet/UnitTest1.cs | 72 ++++ Projects/Packet/Packet/packages.config | 5 + 7 files changed, 774 insertions(+) create mode 100644 Projects/Packet/Packet/.gitignore create mode 100644 Projects/Packet/Packet/MultiplayerToolkit/Packet.cs create mode 100644 Projects/Packet/Packet/Packet.csproj create mode 100644 Projects/Packet/Packet/Packet.sln create mode 100644 Projects/Packet/Packet/Properties/AssemblyInfo.cs create mode 100644 Projects/Packet/Packet/UnitTest1.cs create mode 100644 Projects/Packet/Packet/packages.config (limited to 'Projects/Packet') diff --git a/Projects/Packet/Packet/.gitignore b/Projects/Packet/Packet/.gitignore new file mode 100644 index 0000000..9bf6cfb --- /dev/null +++ b/Projects/Packet/Packet/.gitignore @@ -0,0 +1,194 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +#Sandcastle generated documentation +[Hh]elp/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +!packages/build/ + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +*.ide diff --git a/Projects/Packet/Packet/MultiplayerToolkit/Packet.cs b/Projects/Packet/Packet/MultiplayerToolkit/Packet.cs new file mode 100644 index 0000000..bce39b0 --- /dev/null +++ b/Projects/Packet/Packet/MultiplayerToolkit/Packet.cs @@ -0,0 +1,389 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Text; +#if UNITY_5_3_OR_NEWER +using UnityEngine; +#endif + +namespace MultiplayerToolkit +{ + public enum EPacketMode + { + Write = 0, + Read = 1, + } + + /// + /// 读写通用的简易packet + /// 网络包,通用结构,无论是TCP\UDP还是Steamn + /// 结构: + /// -------------------------------------------------- + /// 2bytes (ushort)包长度,不含这2字节) + /// (-------------------------------------------------- + /// 1byte 消息类型,内置消息、玩家自定义消息 + /// (2byte) (如果是玩家自定义消息,提供一个mod序号,Steam.UGC.Item的id是ulong 8bytes有点大,换成序号,最多支持65535个mod) + /// 2byte (ushort)消息ID 0-65535 + /// 内容 + /// --------------------------------------------------) + /// + public class Packet : IDisposable + { + // 写入缓冲区 + private List writableBuffer; + + // 读取缓冲区,有效数据一定是从头开始 + private byte[] readableBuffer; + private int readPos; + + private EPacketMode m_Mode; + public EPacketMode mode { get { return m_Mode; } } + + private bool disposed; + + #region 创建 + + public static Packet GetWritablePacket() + { + Packet packet = new Packet(); + packet.m_Mode = EPacketMode.Write; + packet.writableBuffer = new List(); + packet.readableBuffer = null; + packet.readPos = 0; + return packet; + } + + public static Packet GetWritablePacket(Packet readable) + { + if (readable.mode != EPacketMode.Read) + return null; + Packet packet = GetWritablePacket(); + packet.Write(readable.readableBuffer); + return packet; + } + + public static Packet GetReadablePacket(byte[] srcToCopy, int offset = 0, int length = -1) + { + Packet packet = new Packet(); + packet.m_Mode = EPacketMode.Read; + packet.writableBuffer = null; + int len = length; + if (length == -1) + { + len = srcToCopy.Length - offset; + } + packet.readableBuffer = new byte[len]; + Array.Copy(srcToCopy, offset, packet.readableBuffer, 0, len); + packet.readPos = 0; + return packet; + } + + public static Packet GetReadablePacket(Packet writable) + { + if (writable.mode != EPacketMode.Write) + return null; + Packet packet = GetReadablePacket(writable.ToArray()); + return packet; + } + + #endregion + + private Packet() + { + this.disposed = false; + } + + public void Reset(bool bReset = true) + { + if (!bReset) + { + return; + } + if (mode == EPacketMode.Write) + { + this.writableBuffer.Clear(); + } + else if (mode == EPacketMode.Read) + { + Array.Clear(this.readableBuffer, 0, this.readableBuffer.Length); + readPos = 0; + } + } + + private static T[] SubArray(T[] data, int index, int length) + { + T[] result = new T[length]; + Array.Copy(data, index, result, 0, length); + return result; + } + + #region 写入 + /// + /// 开头写入一个int为当前writableBuffer长度,不含这个长度 + /// + public void InsertLength() + { + this.writableBuffer.InsertRange(0, BitConverter.GetBytes(this.writableBuffer.Count)); + } + + /// + /// 开头写入一个int + /// + /// + public void InsertInt(int _value) + { + this.writableBuffer.InsertRange(0, BitConverter.GetBytes(_value)); + } + + /// + /// 返回创建的数组,不要频繁调用 + /// + /// + public byte[] ToArray() + { + if (this.mode != EPacketMode.Write) + return null; + return this.writableBuffer.ToArray(); + } + + /// + /// 写入了多少内容 + /// + /// + public int GetWritableBufferLength() + { + return this.writableBuffer.Count; + } + + public void Write(byte _value) + { + this.writableBuffer.Add(_value); + } + + public void Write(byte[] _value) + { + this.writableBuffer.AddRange(_value); + } + + public void Write(short _value) + { + this.writableBuffer.AddRange(BitConverter.GetBytes(_value)); + } + + public void Write(int _value) + { + this.writableBuffer.AddRange(BitConverter.GetBytes(_value)); + } + + public void Write(long _value) + { + this.writableBuffer.AddRange(BitConverter.GetBytes(_value)); + } + + public void Write(float _value) + { + this.writableBuffer.AddRange(BitConverter.GetBytes(_value)); + } + + public void Write(bool _value) + { + this.writableBuffer.AddRange(BitConverter.GetBytes(_value)); + } + + public void Write(string _value) + { + this.Write((int)_value.Length); + this.writableBuffer.AddRange(Encoding.ASCII.GetBytes(_value)); + } + +#if UNITY_5_3_OR_NEWER + + public void Write(Vector3 _value) + { + this.Write(_value.x); + this.Write(_value.y); + this.Write(_value.z); + } + + public void Write(Quaternion _value) + { + this.Write(_value.x); + this.Write(_value.y); + this.Write(_value.z); + this.Write(_value.w); + } +#endif + + #endregion + + #region 读取 + + public void RewindReadPos(int step, bool bRewind = true) + { + if (bRewind) + { + this.readPos -= step; + } + } + + public int GetUnreadLength() + { + return this.readableBuffer.Length - this.readPos; + } + + public byte ReadByte(bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + byte value = this.readableBuffer[this.readPos]; + if (_moveReadPos) + { + this.readPos++; + } + return value; + } + throw new Exception("Could not read value of type 'byte'!"); + } + + public byte[] ReadBytes(int _length, bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + byte[] value = SubArray(this.readableBuffer, this.readPos, _length); + if (_moveReadPos) + { + this.readPos += _length; + } + return value; + } + throw new Exception("Could not read value of type 'byte[]'!"); + } + + public short ReadShort(bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + short value = BitConverter.ToInt16(this.readableBuffer, this.readPos); + if (_moveReadPos) + { + this.readPos += 2; + } + return value; + } + throw new Exception("Could not read value of type 'short'!"); + } + + public int ReadInt(bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + int value = BitConverter.ToInt32(this.readableBuffer, this.readPos); + if (_moveReadPos) + { + this.readPos += 4; + } + return value; + } + throw new Exception("Could not read value of type 'int'!"); + } + + public long ReadLong(bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + long value = BitConverter.ToInt64(this.readableBuffer, this.readPos); + if (_moveReadPos) + { + this.readPos += 8; + } + return value; + } + throw new Exception("Could not read value of type 'long'!"); + } + + public float ReadFloat(bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + float value = BitConverter.ToSingle(this.readableBuffer, this.readPos); + if (_moveReadPos) + { + this.readPos += 4; + } + return value; + } + throw new Exception("Could not read value of type 'float'!"); + } + + public bool ReadBool(bool _moveReadPos = true) + { + if (this.readableBuffer.Length > this.readPos) + { + bool value = BitConverter.ToBoolean(this.readableBuffer, this.readPos); + if (_moveReadPos) + { + this.readPos++; + } + return value; + } + throw new Exception("Could not read value of type 'bool'!"); + } + + public string ReadString(bool _moveReadPos = true) + { + string result; + try + { + int num = this.ReadInt(true); + string @string = Encoding.ASCII.GetString(this.readableBuffer, this.readPos, num); + if (_moveReadPos && @string.Length > 0) + { + this.readPos += num; + } + result = @string; + } + catch (Exception e) + { + throw new Exception("Could not read value of type 'string'!"); + } + return result; + } + +#if UNITY_5_3_OR_NEWER + + public Vector3 ReadVector3(bool moveReadPos = true) + { + return new Vector3(this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos)); + } + + public Quaternion ReadQuaternion(bool moveReadPos = true) + { + return new Quaternion(this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos)); + } +#endif + + #endregion + + protected virtual void Dispose(bool _disposing) + { + if (!this.disposed) + { + if (_disposing) + { + this.writableBuffer = null; + this.readableBuffer = null; + this.readPos = 0; + } + this.disposed = true; + } + } + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + } +} diff --git a/Projects/Packet/Packet/Packet.csproj b/Projects/Packet/Packet/Packet.csproj new file mode 100644 index 0000000..fc2068c --- /dev/null +++ b/Projects/Packet/Packet/Packet.csproj @@ -0,0 +1,69 @@ + + + + + + Debug + AnyCPU + {602EEAD0-42FE-4473-9B41-70C14D3AD156} + Library + Properties + Packet + Packet + v4.7.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + + + + + + + + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + + \ No newline at end of file diff --git a/Projects/Packet/Packet/Packet.sln b/Projects/Packet/Packet/Packet.sln new file mode 100644 index 0000000..0849e6b --- /dev/null +++ b/Projects/Packet/Packet/Packet.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33213.308 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packet", "Packet.csproj", "{602EEAD0-42FE-4473-9B41-70C14D3AD156}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Debug|Any CPU.Build.0 = Debug|Any CPU + {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Release|Any CPU.ActiveCfg = Release|Any CPU + {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0AA0B9B6-7243-4120-9F50-2D4B6D59E1C9} + EndGlobalSection +EndGlobal diff --git a/Projects/Packet/Packet/Properties/AssemblyInfo.cs b/Projects/Packet/Packet/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..808412c --- /dev/null +++ b/Projects/Packet/Packet/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Packet")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("P R C")] +[assembly: AssemblyProduct("Packet")] +[assembly: AssemblyCopyright("Copyright © P R C 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("602eead0-42fe-4473-9b41-70c14d3ad156")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Projects/Packet/Packet/UnitTest1.cs b/Projects/Packet/Packet/UnitTest1.cs new file mode 100644 index 0000000..c014389 --- /dev/null +++ b/Projects/Packet/Packet/UnitTest1.cs @@ -0,0 +1,72 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace MultiplayerToolkit +{ + [TestClass] + public class MultiplayerToolkitTest + { + [TestMethod] + public void TestReadAndWrite() + { + Packet packet = Packet.GetWritablePacket(); + + Assert.AreEqual(packet.mode, EPacketMode.Write); + packet.Write(1); + packet.Write(false); + packet.Write("hello, world"); + packet.Write((byte)13); + packet.Write(12312.3333f); + packet.Write((short)1245); + packet.Write(long.MaxValue); + packet.Write(long.MinValue); + packet.InsertLength(); + + Packet read = Packet.GetReadablePacket(packet); + + Assert.AreEqual(read.mode, EPacketMode.Read); + read.ReadInt(); // length + Assert.AreEqual(1, read.ReadInt()); + Assert.AreEqual(false, read.ReadBool()); + Assert.AreEqual("hello, world", read.ReadString()); + Assert.AreEqual((byte)13, read.ReadByte()); + Assert.AreEqual(12312.3333f, read.ReadFloat()); + Assert.AreEqual((short)1245, read.ReadShort()); + Assert.AreEqual((long)long.MaxValue, read.ReadLong()); + Assert.AreEqual((long)long.MinValue, read.ReadLong()); + } + + [TestMethod] + public void TestReadAndWrite2() + { + Packet packet = Packet.GetWritablePacket(); + + Assert.AreEqual(packet.mode, EPacketMode.Write); + packet.Write(1); + packet.Write(false); + packet.Write("hello, world"); + packet.Write((byte)13); + packet.Write(12312.3333f); + packet.Write((short)1245); + packet.Write(long.MaxValue); + packet.Write(long.MinValue); + packet.InsertLength(); + + Packet read = Packet.GetReadablePacket(packet.ToArray()); + + Assert.AreEqual(read.mode, EPacketMode.Read); + read.ReadInt(); // length + Assert.AreEqual(1, read.ReadInt()); + read.RewindReadPos(4); + read.ReadInt(); + Assert.AreEqual(false, read.ReadBool()); + Assert.AreEqual("hello, world", read.ReadString()); + Assert.AreEqual((byte)13, read.ReadByte()); + Assert.AreEqual(12312.3333f, read.ReadFloat()); + Assert.AreEqual((short)1245, read.ReadShort()); + Assert.AreEqual((long)long.MaxValue, read.ReadLong()); + Assert.AreEqual((long)long.MinValue, read.ReadLong()); + } + + } +} diff --git a/Projects/Packet/Packet/packages.config b/Projects/Packet/Packet/packages.config new file mode 100644 index 0000000..54eb31a --- /dev/null +++ b/Projects/Packet/Packet/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file -- cgit v1.1-26-g67d0