Kaynağa Gözat

删除连接成功但是超过10秒还未发第一个消息过来的channel,防止别人攻击

tanghai 7 yıl önce
ebeveyn
işleme
a53a85301e

+ 6 - 2
Unity/Assets/Scripts/Module/Message/Network/KCP/KChannel.cs

@@ -31,7 +31,9 @@ namespace ETModel
 		public bool isRecvFirstKcpMessage;
 		private readonly IPEndPoint remoteEndPoint;
 
-		private uint lastRecvTime;
+		public uint lastRecvTime;
+
+		public uint CreateTime;
 
 		public uint RemoteConn;
 
@@ -61,6 +63,7 @@ namespace ETModel
 			this.isConnected = true;
 			this.isRecvFirstKcpMessage = false;
 			this.lastRecvTime = kService.TimeNow;
+			this.CreateTime = kService.TimeNow;
 		}
 
 		// connect
@@ -73,6 +76,7 @@ namespace ETModel
 			this.remoteEndPoint = remoteEndPoint;
 			this.isRecvFirstKcpMessage = false;
 			this.lastRecvTime = kService.TimeNow;
+			this.CreateTime = kService.TimeNow;
 			this.Connect();
 		}
 
@@ -343,7 +347,7 @@ namespace ETModel
 					return;
 				}
 
-				lastRecvTime = this.GetService().TimeNow;
+				this.lastRecvTime = this.GetService().TimeNow;
 
 				this.OnRead(packet);
 			}

+ 55 - 4
Unity/Assets/Scripts/Module/Message/Network/KCP/KService.cs

@@ -2,7 +2,9 @@
 using System.Collections.Generic;
 using System.Net;
 using System.Net.Sockets;
+#if SERVER
 using System.Runtime.InteropServices;
+#endif
 
 namespace ETModel
 {
@@ -20,13 +22,20 @@ namespace ETModel
 
 		private uint IdGenerater = 1000;
 
+		// KService创建的时间
+		public long StartTime;
+		
+		// 当前时间 - KService创建的时间
 		public uint TimeNow { get; private set; }
 
 		private Socket socket;
 
 		private readonly Dictionary<long, KChannel> localConnChannels = new Dictionary<long, KChannel>();
 
+		// 记录等待连接的channel,10秒后或者第一个消息过来才会从这个dict中删除
 		private readonly Dictionary<uint, KChannel> waitConnectChannels = new Dictionary<uint, KChannel>();
+		private readonly List<uint> connectTimeoutChannels = new List<uint>();
+		private uint lastCheckTime;
 
 		private readonly byte[] cache = new byte[8192];
 
@@ -47,7 +56,8 @@ namespace ETModel
 
 		public KService(IPEndPoint ipEndPoint)
 		{
-			this.TimeNow = (uint)TimeHelper.ClientNow();
+			this.StartTime = TimeHelper.ClientNow();
+			this.TimeNow = (uint)(TimeHelper.ClientNow() - this.StartTime);
 			this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 			//this.socket.Blocking = false;
 			this.socket.Bind(ipEndPoint);
@@ -65,7 +75,8 @@ namespace ETModel
 
 		public KService()
 		{
-			this.TimeNow = (uint)TimeHelper.ClientNow();
+			this.StartTime = TimeHelper.ClientNow();
+			this.TimeNow = (uint)(TimeHelper.ClientNow() - this.StartTime);
 			this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 			//this.socket.Blocking = false;
 			this.socket.Bind(new IPEndPoint(IPAddress.Any, 0));
@@ -159,7 +170,7 @@ namespace ETModel
 
 						localConn = ++this.IdGenerater;
 						kChannel = new KChannel(localConn, remoteConn, this.socket, acceptIpEndPoint, this);
-						this.localConnChannels[kChannel.Id] = kChannel;
+						this.localConnChannels[kChannel.LocalConn] = kChannel;
 						this.waitConnectChannels[remoteConn] = kChannel;
 
 						kChannel.HandleAccept(remoteConn);
@@ -316,10 +327,12 @@ namespace ETModel
 
 		public override void Update()
 		{
-			this.TimeNow = (uint)TimeHelper.ClientNow();
+			this.TimeNow = (uint)(TimeHelper.ClientNow() - this.StartTime);
 
 			this.Recv();
 
+			this.CheckWaitTimeout();
+			
 			this.TimerOut();
 
 			foreach (long id in updateChannels)
@@ -348,6 +361,44 @@ namespace ETModel
 			}
 		}
 
+		// 2秒钟检查一次, 删除连接成功但是超过10秒还未发第一个消息过来的channel
+		private void CheckWaitTimeout()
+		{
+			if (this.TimeNow - this.lastCheckTime < 2000)
+			{
+				return;
+			}
+
+			this.lastCheckTime = this.TimeNow;
+
+			if (this.waitConnectChannels.Count == 0)
+			{
+				return;
+			}
+
+			this.connectTimeoutChannels.Clear();
+			foreach (KeyValuePair<uint,KChannel> kv in this.waitConnectChannels)
+			{
+				if (this.TimeNow - kv.Value.CreateTime < 10000)
+				{
+					continue;
+				}
+				this.connectTimeoutChannels.Add(kv.Key);
+			}
+
+			foreach (uint remoteConn in this.connectTimeoutChannels)
+			{
+				KChannel kChannel;
+				if (!this.waitConnectChannels.TryGetValue(remoteConn, out kChannel))
+				{
+					continue;
+				}
+
+				this.waitConnectChannels.Remove(remoteConn);
+				this.Remove(kChannel.LocalConn);
+			}
+		}
+
 		// 计算到期需要update的channel
 		private void TimerOut()
 		{