Просмотр исходного кода

ENet: 实现ConnectAsync和ReceiveAsync方法因此可以实现大量并发连接

tanghai 13 лет назад
Родитель
Сommit
61dd395d4d

+ 4 - 4
CSharp/App/Editor/Editor.csproj

@@ -113,14 +113,14 @@
     <Folder Include="Properties\" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\Infrastructure\Infrastructure.csproj">
+      <Project>{48a2e149-0dac-41b4-bb54-dfbccd6d42b3}</Project>
+      <Name>Infrastructure</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Modules\BehaviorTree\BehaviorTree.csproj">
       <Project>{6CD185D1-08E0-4729-A999-2D5B57BA8193}</Project>
       <Name>BehaviorTree</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\Platform\Infrastructure\Infrastructure.csproj">
-      <Project>{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}</Project>
-      <Name>Infrastructure</Name>
-    </ProjectReference>
     <ProjectReference Include="..\Modules\Robot\Robot.csproj">
       <Project>{5d6ecbcd-be14-4dcb-baec-57089748b164}</Project>
       <Name>Robot</Name>

+ 4 - 2
CSharp/App/Editor/NLog.config

@@ -2,8 +2,10 @@
 
 <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 	<targets>
-		<target name="file" xsi:type="File" fileName="${basedir}/Log.txt"
-		        layout="${longdate} ${threadid:padCharacter=0:padding=4:fixedLength=true} ${callsite:className=false:includeSourcePath=false:methodName=false:fileName=true}  ${message}" />
+		<target name="file" xsi:type="File" 
+			fileName="${basedir}/Log.txt"
+			deleteOldFileOnStartup="true"
+			layout="${longdate} ${threadid:padCharacter=0:padding=4:fixedLength=true} ${callsite:className=false:includeSourcePath=false:methodName=false:fileName=true}  ${message}" />
 	</targets>
 	<rules>
 		<logger name="*" minlevel="Trace" writeTo="file" />

+ 0 - 0
CSharp/Platform/Infrastructure/AutoPopulateExportedViewsBehavior.cs → CSharp/App/Infrastructure/AutoPopulateExportedViewsBehavior.cs


+ 13 - 0
CSharp/App/Infrastructure/ENetUpdateEvent.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Practices.Prism.Events;
+
+namespace Infrastructure
+{
+	public class ENetUpdateEvent : CompositePresentationEvent<Action>
+	{
+	}
+}

+ 0 - 0
CSharp/Platform/Infrastructure/IViewRegionRegistration.cs → CSharp/App/Infrastructure/IViewRegionRegistration.cs


+ 1 - 0
CSharp/Platform/Infrastructure/Infrastructure.csproj → CSharp/App/Infrastructure/Infrastructure.csproj

@@ -47,6 +47,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AutoPopulateExportedViewsBehavior.cs" />
+    <Compile Include="ENetUpdateEvent.cs" />
     <Compile Include="IViewRegionRegistration.cs" />
     <Compile Include="ViewExportAttribute.cs" />
   </ItemGroup>

+ 0 - 0
CSharp/Platform/Infrastructure/Packages.config → CSharp/App/Infrastructure/Packages.config


+ 0 - 0
CSharp/Platform/Infrastructure/ViewExportAttribute.cs → CSharp/App/Infrastructure/ViewExportAttribute.cs


+ 2 - 2
CSharp/App/Modules/BehaviorTree/BehaviorTree.csproj

@@ -80,8 +80,8 @@
       <Project>{72e16572-fc1f-4a9e-bc96-035417239298}</Project>
       <Name>ELog</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\..\Platform\Infrastructure\Infrastructure.csproj">
-      <Project>{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}</Project>
+    <ProjectReference Include="..\..\Infrastructure\Infrastructure.csproj">
+      <Project>{48a2e149-0dac-41b4-bb54-dfbccd6d42b3}</Project>
       <Name>Infrastructure</Name>
     </ProjectReference>
   </ItemGroup>

+ 4 - 4
CSharp/App/Modules/Robot/Robot.csproj

@@ -69,14 +69,14 @@
       <Project>{72e16572-fc1f-4a9e-bc96-035417239298}</Project>
       <Name>ELog</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\..\Platform\Infrastructure\Infrastructure.csproj">
-      <Project>{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}</Project>
-      <Name>Infrastructure</Name>
-    </ProjectReference>
     <ProjectReference Include="..\..\..\ThirdParty\ENetCS\ENetCS.csproj">
       <Project>{d0b4cfac-a368-4742-9863-68776cfa9938}</Project>
       <Name>ENetCS</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\Infrastructure\Infrastructure.csproj">
+      <Project>{48a2e149-0dac-41b4-bb54-dfbccd6d42b3}</Project>
+      <Name>Infrastructure</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />

+ 24 - 13
CSharp/App/Modules/Robot/RobotViewModel.cs

@@ -1,18 +1,25 @@
 using System;
 using System.ComponentModel.Composition;
-using System.Threading;
 using System.Threading.Tasks;
+using System.Windows.Threading;
 using ELog;
+using Microsoft.Practices.Prism.Events;
 using Microsoft.Practices.Prism.ViewModel;
 using ENet;
+using Infrastructure;
 
 namespace Modules.Robot
 {
 	[Export(contractType: typeof (RobotViewModel)), PartCreationPolicy(creationPolicy: CreationPolicy.NonShared)]
 	internal class RobotViewModel : NotificationObject
 	{
-		private Host host;
+		private ENetHost host;
 		private string logText = "";
+		private IEventAggregator eventAggregator = new EventAggregator();
+		private readonly DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Normal)
+		{
+			Interval = new TimeSpan(0, 0, 0, 0, 50)
+		};
 
 		public string LogText
 		{
@@ -34,26 +41,30 @@ namespace Modules.Robot
 		public RobotViewModel()
 		{
 			Library.Initialize();
+			host = new ENetHost(8888, Native.ENET_PROTOCOL_MAXIMUM_PEER_ID);
 
-			Task.Factory.StartNew(() =>
-				{
-				
-				});
-
-
+			timer.Tick += delegate { this.host.Run(); };
+			timer.Start();
 		}
 
-		public async Task<Peer> StartClient()
+		public async void StartClient()
 		{
-			
+			try
+			{
+				await host.ConnectAsync(new Address { Host = "192.168.10.246", Port = 8901 }, 2, 0);
+			}
+			catch (ENetException e)
+			{
+				Log.Debug(e.Message);
+				return;
+			}
 		}
 
 		public void Start()
 		{
-			var peer = StartClient().Result;
-			if (peer.State == PeerState.Connected)
+			for (int i = 0; i < 4095; ++i)
 			{
-				Log.Debug("11111111111");
+				StartClient();
 			}
 		}
 	}

+ 2 - 2
CSharp/App/Modules/WaiGua/WaiGua.csproj

@@ -81,8 +81,8 @@
     <None Include="Packages.config" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\..\Platform\Infrastructure\Infrastructure.csproj">
-      <Project>{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}</Project>
+    <ProjectReference Include="..\..\Infrastructure\Infrastructure.csproj">
+      <Project>{48a2e149-0dac-41b4-bb54-dfbccd6d42b3}</Project>
       <Name>Infrastructure</Name>
     </ProjectReference>
   </ItemGroup>

+ 15 - 15
CSharp/CSharp.sln

@@ -12,8 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{EAEF82
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platform", "Platform", "{ADBF5F67-B480-4A93-9D50-C81856FC61A9}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "Platform\Infrastructure\Infrastructure.csproj", "{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}"
-EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{6E9D97F0-4243-452E-B832-1A855B8118EB}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BehaviorTree", "App\Modules\BehaviorTree\BehaviorTree.csproj", "{6CD185D1-08E0-4729-A999-2D5B57BA8193}"
@@ -37,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ENetCS", "ThirdParty\ENetCS
 		{C9992B7C-313E-4C9F-A954-640D01EDFB58} = {C9992B7C-313E-4C9F-A954-640D01EDFB58}
 	EndProjectSection
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "App\Infrastructure\Infrastructure.csproj", "{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -49,18 +49,6 @@ Global
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Win32.ActiveCfg = Debug|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Any CPU.Build.0 = Release|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Win32.ActiveCfg = Release|Any CPU
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|x86.ActiveCfg = Release|Any CPU
 		{6CD185D1-08E0-4729-A999-2D5B57BA8193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{6CD185D1-08E0-4729-A999-2D5B57BA8193}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{6CD185D1-08E0-4729-A999-2D5B57BA8193}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -161,6 +149,18 @@ Global
 		{D0B4CFAC-A368-4742-9863-68776CFA9938}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 		{D0B4CFAC-A368-4742-9863-68776CFA9938}.Release|Win32.ActiveCfg = Release|Any CPU
 		{D0B4CFAC-A368-4742-9863-68776CFA9938}.Release|x86.ActiveCfg = Release|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|Win32.ActiveCfg = Release|Any CPU
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -168,7 +168,7 @@ Global
 	GlobalSection(NestedProjects) = preSolution
 		{C4C64188-4FAE-4CC3-A9E6-D9D4AF7429B6} = {6E9D97F0-4243-452E-B832-1A855B8118EB}
 		{C46F3337-0F48-4A72-84AD-8FDD1F159BB0} = {6E9D97F0-4243-452E-B832-1A855B8118EB}
-		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3} = {ADBF5F67-B480-4A93-9D50-C81856FC61A9}
+		{48A2E149-0DAC-41B4-BB54-DFBCCD6D42B3} = {6E9D97F0-4243-452E-B832-1A855B8118EB}
 		{72E16572-FC1F-4A9E-BC96-035417239298} = {ADBF5F67-B480-4A93-9D50-C81856FC61A9}
 		{3A98B35C-DEA8-489C-9203-263FFB6B065D} = {ADBF5F67-B480-4A93-9D50-C81856FC61A9}
 		{6CD185D1-08E0-4729-A999-2D5B57BA8193} = {C4C64188-4FAE-4CC3-A9E6-D9D4AF7429B6}

+ 11 - 5
CSharp/ThirdParty/ENetCS/ENetCS.csproj

@@ -43,21 +43,27 @@
     <Compile Include="Address.cs" />
     <Compile Include="AddressType.cs" />
     <Compile Include="ENetException.cs" />
-    <Compile Include="ENetClient.cs" />
-    <Compile Include="Event.cs" />
+    <Compile Include="ENetEvent.cs" />
     <Compile Include="EventType.cs" />
-    <Compile Include="Host.cs" />
+    <Compile Include="ENetHost.cs" />
     <Compile Include="Library.cs" />
     <Compile Include="Native.cs" />
     <Compile Include="Native.Structs.cs" />
-    <Compile Include="Packet.cs" />
+    <Compile Include="ENetPacket.cs" />
     <Compile Include="PacketFlags.cs" />
-    <Compile Include="Peer.cs" />
+    <Compile Include="ENetPeer.cs" />
+    <Compile Include="PeerManager.cs" />
     <Compile Include="PeerState.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Platform\ELog\ELog.csproj">
+      <Project>{72e16572-fc1f-4a9e-bc96-035417239298}</Project>
+      <Name>ELog</Name>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

+ 0 - 60
CSharp/ThirdParty/ENetCS/ENetClient.cs

@@ -1,60 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ENet
-{
-	public class ENetClient
-	{
-		private readonly Host host;
-
-		private readonly Dictionary<uint, TaskCompletionSource<Peer>> peerTcs = new Dictionary<uint, TaskCompletionSource<Peer>>();
-
-		public ENetClient(uint peerLimit)
-		{
-			host = new Host(null, peerLimit);
-		}
-
-		public void Poll(int timeout)
-		{
-			while (host.Service(timeout) >= 0)
-			{
-				Event e;
-				while (host.CheckEvents(out e) > 0)
-				{
-					switch (e.Type)
-					{
-						case EventType.Connect:
-						{
-							var tcs = peerTcs[e.Peer.ConnectID];
-							tcs.TrySetResult(e.Peer);
-							peerTcs.Remove(e.Peer.ConnectID);
-							break;
-						}
-						case EventType.Receive:
-						{
-							break;
-						}
-						case EventType.Disconnect:
-						{
-							break;
-						}
-					}
-				}
-			}
-		}
-
-		public Task<Peer> ConnectAsync(string hostName, ushort port)
-		{
-			var tcs = new TaskCompletionSource<Peer>();
-			var address = new Address { Host = "192.168.10.246", Port = 8901 };
-			var peer = this.host.Connect(address, 2, 1);
-			uint id = peer.ConnectID;
-			peerTcs[id] = tcs;
-			var t = tcs.Task;
-			return t;
-		}
-	}
-}

+ 15 - 6
CSharp/ThirdParty/ENetCS/Event.cs → CSharp/ThirdParty/ENetCS/ENetEvent.cs

@@ -19,15 +19,19 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #endregion
 
+using ELog;
+
 namespace ENet
 {
-	public unsafe struct Event
+	public unsafe struct ENetEvent
 	{
+		private readonly ENetHost host;
 		private Native.ENetEvent e;
 
-		public Event(Native.ENetEvent e)
+		public ENetEvent(ENetHost host, Native.ENetEvent e)
 		{
 			this.e = e;
+			this.host = host;
 		}
 
 		public byte ChannelID
@@ -58,7 +62,7 @@ namespace ENet
 			}
 		}
 
-		public Packet Packet
+		public ENetPacket Packet
 		{
 			get
 			{
@@ -66,11 +70,11 @@ namespace ENet
 				{
 					return null;
 				}
-				return new Packet(this.e.packet);
+				return new ENetPacket(this.e.packet);
 			}
 		}
 
-		public Peer Peer
+		public ENetPeer ENetPeer
 		{
 			get
 			{
@@ -78,7 +82,12 @@ namespace ENet
 				{
 					return null;
 				}
-				return new Peer(this.e.peer);
+				var data = (int)e.peer->data;
+				if (!this.host.Peers.ContainsKey(data))
+				{
+					return null;
+				}
+				return this.host.Peers[data];
 			}
 		}
 

+ 62 - 12
CSharp/ThirdParty/ENetCS/Host.cs → CSharp/ThirdParty/ENetCS/ENetHost.cs

@@ -19,20 +19,24 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #endregion
 
+using ELog;
 using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
 
 namespace ENet
 {
-	public sealed unsafe class Host : IDisposable
+	public sealed unsafe class ENetHost : IDisposable
 	{
 		private Native.ENetHost* host;
+		private PeerManager peerManager = new PeerManager();
 
-		public Host(ushort port, uint peerLimit):
+		public ENetHost(ushort port, uint peerLimit):
 			this(new Address { Port = port }, peerLimit)
 		{
 		}
 
-		public Host(Address? address, uint peerLimit, uint channelLimit = 0, 
+		public ENetHost(Address? address, uint peerLimit, uint channelLimit = 0, 
 				uint incomingBandwidth = 0, uint outgoingBandwidth = 0, bool enableCrc = true)
 		{
 			if (peerLimit > Native.ENET_PROTOCOL_MAXIMUM_PEER_ID)
@@ -66,7 +70,7 @@ namespace ENet
 			}
 		}
 
-		~Host()
+		~ENetHost()
 		{
 			this.Dispose(false);
 		}
@@ -91,6 +95,14 @@ namespace ENet
 			}
 		}
 
+		public PeerManager Peers
+		{
+			get
+			{
+				return peerManager;
+			}
+		}
+
 		private static void CheckChannelLimit(uint channelLimit)
 		{
 			if (channelLimit > Native.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
@@ -99,7 +111,7 @@ namespace ENet
 			}
 		}
 
-		public void Broadcast(byte channelID, ref Packet packet)
+		public void Broadcast(byte channelID, ref ENetPacket packet)
 		{
 			Native.enet_host_broadcast(this.host, channelID, packet.NativeData);
 			packet.NativeData = null; // Broadcast automatically clears this.
@@ -115,26 +127,32 @@ namespace ENet
 			Native.enet_host_compress(this.host, null);
 		}
 
-		public int CheckEvents(out Event e)
+		public int CheckEvents(out ENetEvent e)
 		{
 			Native.ENetEvent nativeEvent;
 			int ret = Native.enet_host_check_events(this.host, out nativeEvent);
-			e = new Event(nativeEvent);
+			e = new ENetEvent(this, nativeEvent);
 			return ret;
 		}
 
-		public Peer Connect(Address address, uint channelLimit, uint data)
+		public Task<ENetPeer> ConnectAsync(
+			Address address, uint channelLimit = Native.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT, 
+			uint data = 0)
 		{
 			CheckChannelLimit(channelLimit);
 
+			var tcs = new TaskCompletionSource<ENetPeer>();
 			Native.ENetAddress nativeAddress = address.NativeData;
 			Native.ENetPeer* p = Native.enet_host_connect(this.host, ref nativeAddress, channelLimit, data);
 			if (p == null)
 			{
 				throw new ENetException(0, "Host connect call failed.");
 			}
-			var peer = new Peer(p);
-			return peer;
+			new ENetPeer(this, p)
+			{
+				Connected = e => tcs.TrySetResult(e.ENetPeer)
+			};
+			return tcs.Task;
 		}
 
 		public void Flush()
@@ -151,7 +169,7 @@ namespace ENet
 			return Native.enet_host_service(this.host, null, (uint) timeout);
 		}
 
-		public int Service(int timeout, out Event e)
+		public int Service(int timeout, out ENetEvent e)
 		{
 			if (timeout < 0)
 			{
@@ -160,7 +178,7 @@ namespace ENet
 			Native.ENetEvent nativeEvent;
 
 			int ret = Native.enet_host_service(this.host, out nativeEvent, (uint) timeout);
-			e = new Event(nativeEvent);
+			e = new ENetEvent(this, nativeEvent);
 			return ret;
 		}
 
@@ -174,5 +192,37 @@ namespace ENet
 			CheckChannelLimit(channelLimit);
 			Native.enet_host_channel_limit(this.host, channelLimit);
 		}
+
+		public void Run()
+		{
+			if (this.Service(0) < 0)
+			{
+				return;
+			}
+
+			ENetEvent e;
+			while (this.CheckEvents(out e) > 0)
+			{
+				switch (e.Type)
+				{
+					case EventType.Connect:
+					{
+						e.ENetPeer.Connected(e);
+						break;
+					}
+					case EventType.Receive:
+					{
+						e.ENetPeer.Received(e);
+						break;
+					}
+					case EventType.Disconnect:
+					{
+						Log.Debug("Disconnect");
+						e.ENetPeer.Disconnect(e);
+						break;
+					}
+				}
+			}
+		}
 	}
 }

+ 7 - 7
CSharp/ThirdParty/ENetCS/Packet.cs → CSharp/ThirdParty/ENetCS/ENetPacket.cs

@@ -24,11 +24,11 @@ using System.Runtime.InteropServices;
 
 namespace ENet
 {
-	public unsafe class Packet : IDisposable
+	public sealed unsafe class ENetPacket : IDisposable
 	{
 		private Native.ENetPacket* packet;
 
-		public Packet(Native.ENetPacket* packet)
+		public ENetPacket(Native.ENetPacket* packet)
 		{
 			if (packet == null)
 			{
@@ -37,15 +37,15 @@ namespace ENet
 			this.packet = packet;
 		}
 
-		public Packet(): this(new byte[]{})
+		public ENetPacket(): this(new byte[]{})
 		{
 		}
 
-		public Packet(byte[] data): this(data, 0, data.Length)
+		public ENetPacket(byte[] data): this(data, 0, data.Length)
 		{
 		}
 
-		public Packet(byte[] data, int offset, int length, PacketFlags flags = PacketFlags.None)
+		public ENetPacket(byte[] data, int offset, int length, PacketFlags flags = PacketFlags.None)
 		{
 			if (data == null)
 			{
@@ -65,7 +65,7 @@ namespace ENet
 			}
 		}
 
-		~Packet()
+		~ENetPacket()
 		{
 			Dispose(false);
 		}
@@ -76,7 +76,7 @@ namespace ENet
 			GC.SuppressFinalize(this);
 		}
 
-		protected virtual void Dispose(bool disposing)
+		private void Dispose(bool disposing)
 		{
 			if (this.packet == null)
 			{

+ 87 - 38
CSharp/ThirdParty/ENetCS/Peer.cs → CSharp/ThirdParty/ENetCS/ENetPeer.cs

@@ -24,20 +24,26 @@ using System.Threading.Tasks;
 
 namespace ENet
 {
-	public unsafe class Peer : IDisposable
+	public unsafe class ENetPeer : IDisposable
 	{
+		private readonly ENetHost host;
 		private Native.ENetPeer* peer;
+		private Action<ENetEvent> connected;
+		private Action<ENetEvent> received;
+		private Action<ENetEvent> disconnect;
 
-		public Peer(Native.ENetPeer* peer)
+		public ENetPeer(ENetHost host, Native.ENetPeer* peer)
 		{
 			if (peer == null)
 			{
 				throw new InvalidOperationException("No native peer.");
 			}
 			this.peer = peer;
+			this.host = host;
+			this.host.Peers.Add(this);
 		}
 
-		~Peer()
+		~ENetPeer()
 		{
 			this.Dispose(false);
 		}
@@ -58,63 +64,114 @@ namespace ENet
 			if (disposing)
 			{
 				Native.enet_peer_reset(this.peer);
-				this.peer = null;
 			}
+			this.host.Peers.Remove((int)this.peer->data);
+			this.peer = null;
 		}
 
-		public void ConfigureThrottle(uint interval, uint acceleration, uint deceleration)
+		// peer连接上了调用该回调方法
+		public Action<ENetEvent> Connected
 		{
-			Native.enet_peer_throttle_configure(this.peer, interval, acceleration, deceleration);
+			get
+			{
+				if (connected == null)
+				{
+					return e => { };
+				}
+				return connected;
+			}
+			set
+			{
+				connected = value;
+			}
 		}
 
-		public void Disconnect(uint data)
+		public Action<ENetEvent> Received
 		{
-			Native.enet_peer_disconnect(this.peer, data);
+			get
+			{
+				if (received == null)
+				{
+					return e => { };
+				}
+				return received;
+			}
+			set
+			{
+				received = value;
+			}
 		}
 
-		public void DisconnectLater(uint data)
+		public Action<ENetEvent> Disconnect
 		{
-			Native.enet_peer_disconnect_later(this.peer, data);
+			get
+			{
+				if (disconnect == null)
+				{
+					return e => { };
+				}
+				return disconnect;
+			}
+			set
+			{
+				disconnect = value;
+			}
 		}
 
-		public void DisconnectNow(uint data)
+		public void ConfigureThrottle(uint interval, uint acceleration, uint deceleration)
 		{
-			Native.enet_peer_disconnect_now(this.peer, data);
+			Native.enet_peer_throttle_configure(this.peer, interval, acceleration, deceleration);
 		}
 
-		public void Ping()
+		public void Send(byte channelID, byte[] data)
 		{
-			Native.enet_peer_ping(this.peer);
+			this.Send(channelID, data, 0, data.Length);
 		}
 
-		public bool Receive(out byte channelID, out Packet packet)
+		public void Send(byte channelID, byte[] data, int offset, int length)
 		{
-			Native.ENetPacket* nativePacket = Native.enet_peer_receive(this.peer, out channelID);
-			if (nativePacket == null)
+			using (var packet = new ENetPacket(data, offset, length))
 			{
-				packet = new Packet();
-				return false;
+				this.Send(channelID, packet);
 			}
-			packet = new Packet(nativePacket);
-			return true;
 		}
 
-		public void Send(byte channelID, byte[] data)
+		public void Send(byte channelID, ENetPacket packet)
 		{
-			this.Send(channelID, data, 0, data.Length);
+			Native.enet_peer_send(this.peer, channelID, packet.NativeData);
 		}
 
-		public void Send(byte channelID, byte[] data, int offset, int length)
+		public Task<ENetPacket> ReceiveAsync()
 		{
-			using (var packet = new Packet(data, offset, length))
-			{
-				this.Send(channelID, packet);
-			}
+			var tcs = new TaskCompletionSource<ENetPacket>();
+			this.Received = e => tcs.TrySetResult(e.Packet);
+			return tcs.Task;
 		}
 
-		public void Send(byte channelID, Packet packet)
+		public Task<bool> DisconnectAsync(uint data)
 		{
-			Native.enet_peer_send(this.peer, channelID, packet.NativeData);
+			var tcs = new TaskCompletionSource<bool>();
+			this.Disconnect = e => tcs.TrySetResult(true);
+			Native.enet_peer_disconnect(this.peer, data);
+			return tcs.Task;
+		}
+
+		public Task<bool> DisconnectLaterAsync(uint data)
+		{
+			var tcs = new TaskCompletionSource<bool>();
+			this.Disconnect = e => tcs.TrySetResult(true);
+			Native.enet_peer_disconnect_later(this.peer, data);
+			return tcs.Task;
+		}
+
+		public void DisconnectNow(uint data)
+		{
+			Native.enet_peer_disconnect_now(this.peer, data);
+		}
+
+		public void Ping()
+		{
+			Native.enet_peer_ping(this.peer);
 		}
 
 		public Native.ENetPeer* NativeData
@@ -148,13 +205,5 @@ namespace ENet
 				this.peer->data = value;
 			}
 		}
-
-		public uint ConnectID
-		{
-			get
-			{
-				return this.peer->connectID;
-			}
-		}
 	}
 }

+ 47 - 0
CSharp/ThirdParty/ENetCS/PeerManager.cs

@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+namespace ENet
+{
+	public class PeerManager
+	{
+		private int num = 0;
+		private readonly Dictionary<int, ENetPeer> peers = new Dictionary<int, ENetPeer>();
+
+		public void Add(ENetPeer peer)
+		{
+			++num;
+			unsafe
+			{
+				peer.NativeData->data = (IntPtr)num;
+			}
+			peers[num] = peer;
+		}
+
+		public void Remove(int key)
+		{
+			peers.Remove(key);
+		}
+
+		public bool ContainsKey(int key)
+		{
+			if (peers.ContainsKey(key))
+			{
+				return true;
+			}
+			return false;
+		}
+
+		public ENetPeer this[int key]
+		{
+			get
+			{
+				return this.peers[key];
+			}
+			set
+			{
+				this.peers[key] = value;
+			}
+		}
+	}
+}