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

客户端kcp因为channel很少,可以每帧update,不用计时器,这样可以消除kservice timerout方法里面的gc

tanghai 7 лет назад
Родитель
Сommit
8f74434682

+ 12 - 4
Unity/Assets/Scripts/Module/Message/Network/KCP/KChannel.cs

@@ -32,7 +32,7 @@ namespace ETModel
 		private readonly IPEndPoint remoteEndPoint;
 
 		public uint lastRecvTime;
-
+		
 		public uint CreateTime;
 
 		public uint RemoteConn;
@@ -203,10 +203,13 @@ namespace ETModel
 			try
 			{
 				uint timeNow = this.GetService().TimeNow;
+				
+				this.lastRecvTime = timeNow;
+				
 				this.packet.Bytes.WriteTo(0, KcpProtocalType.SYN);
 				this.packet.Bytes.WriteTo(1, this.LocalConn);
 				this.socket.SendTo(this.packet.Bytes, 0, 5, SocketFlags.None, remoteEndPoint);
-
+				
 				// 200毫秒后再次update发送connect请求
 				this.GetService().AddToUpdateNextTime(timeNow + 200, this.Id);
 			}
@@ -246,16 +249,21 @@ namespace ETModel
 			}
 
 			uint timeNow = this.GetService().TimeNow;
-
+			
 			// 如果还没连接上,发送连接请求
 			if (!this.isConnected)
 			{
 				// 10秒没连接上则报错
-				if (timeNow - this.lastRecvTime > 10 * 1000)
+				if (timeNow - this.CreateTime > 10 * 1000)
 				{
 					this.OnError(ErrorCode.ERR_KcpCantConnect);
 					return;
 				}
+				
+				if (timeNow - this.lastRecvTime < 150)
+				{
+					return;
+				}
 				this.Connect();
 				return;
 			}

+ 53 - 24
Unity/Assets/Scripts/Module/Message/Network/KCP/KService.cs

@@ -24,33 +24,34 @@ namespace ETModel
 
 		// KService创建的时间
 		public long StartTime;
-		
 		// 当前时间 - KService创建的时间
 		public uint TimeNow { get; private set; }
 
 		private Socket socket;
 
 		private readonly Dictionary<long, KChannel> localConnChannels = new Dictionary<long, KChannel>();
+		
+		private readonly byte[] cache = new byte[8192];
+
+		private readonly Queue<long> removedChannels = new Queue<long>();
 
+		#region 连接相关
 		// 记录等待连接的channel,10秒后或者第一个消息过来才会从这个dict中删除
 		private readonly Dictionary<uint, KChannel> waitConnectChannels = new Dictionary<uint, KChannel>();
 		private readonly List<uint> connectTimeoutChannels = new List<uint>();
 		private uint lastCheckTime;
+		#endregion
 
-		private readonly byte[] cache = new byte[8192];
-
-		private readonly Queue<long> removedChannels = new Queue<long>();
-
+		#region 定时器相关
 		// 下帧要更新的channel
 		private readonly HashSet<long> updateChannels = new HashSet<long>();
-
 		// 下次时间更新的channel
 		private readonly MultiMap<long, long> timeId = new MultiMap<long, long>();
-
 		private readonly List<long> timeOutTime = new List<long>();
-
 		// 记录最小时间,不用每次都去MultiMap取第一个值
 		private long minTime;
+		#endregion
+
 
 		private EndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
 
@@ -296,39 +297,68 @@ namespace ETModel
 			return channel;
 		}
 
-		public void AddToUpdateNextTime(long time, long id)
+		public override void Remove(long id)
 		{
-			if (time == 0)
+			KChannel channel;
+			if (!this.localConnChannels.TryGetValue(id, out channel))
 			{
-				this.updateChannels.Add(id);
 				return;
 			}
-			if (time < this.minTime)
+			if (channel == null)
 			{
-				this.minTime = time;
+				return;
 			}
-			this.timeId.Add(time, id);
+			this.removedChannels.Enqueue(id);
+			channel.Dispose();
 		}
 
-		public override void Remove(long id)
+#if !SERVER
+		// 客户端channel很少,直接每帧update所有channel即可,这样可以消除TimerOut方法的gc
+		public void AddToUpdateNextTime(long time, long id)
 		{
-			KChannel channel;
-			if (!this.localConnChannels.TryGetValue(id, out channel))
+		}
+		
+		public override void Update()
+		{
+			this.TimeNow = (uint) (TimeHelper.ClientNow() - this.StartTime);
+
+			this.Recv();
+
+			foreach (var kv in this.localConnChannels)
 			{
-				return;
+				kv.Value.Update();
 			}
-			if (channel == null)
+			
+			while (true)
 			{
+				if (this.removedChannels.Count <= 0)
+				{
+					break;
+				}
+				long id = this.removedChannels.Dequeue();
+				this.localConnChannels.Remove(id);
+			}
+		}
+#else
+		// 服务端需要看channel的update时间是否已到
+		public void AddToUpdateNextTime(long time, long id)
+		{
+			if (time == 0)
+			{	
+				this.updateChannels.Add(id);
 				return;
 			}
-			this.removedChannels.Enqueue(id);
-			channel.Dispose();
+			if (time < this.minTime)
+			{
+				this.minTime = time;
+			}
+			this.timeId.Add(time, id);
 		}
 
 		public override void Update()
 		{
 			this.TimeNow = (uint)(TimeHelper.ClientNow() - this.StartTime);
-
+			
 			this.Recv();
 
 			this.CheckWaitTimeout();
@@ -413,7 +443,6 @@ namespace ETModel
 			{
 				return;
 			}
-
 			this.timeOutTime.Clear();
 
 			foreach (KeyValuePair<long, List<long>> kv in this.timeId.GetDictionary())
@@ -426,7 +455,6 @@ namespace ETModel
 				}
 				this.timeOutTime.Add(k);
 			}
-
 			foreach (long k in this.timeOutTime)
 			{
 				foreach (long v in this.timeId[k])
@@ -437,5 +465,6 @@ namespace ETModel
 				this.timeId.Remove(k);
 			}
 		}
+#endif
 	}
 }