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

修复一个路由重连的bug

tanghai 2 лет назад
Родитель
Сommit
ff7cedd80e

+ 1 - 0
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterAddressComponentSystem.cs

@@ -57,6 +57,7 @@ namespace ET.Client
             }
 
             string address = self.Info.Routers[self.RouterIndex++ % self.Info.Routers.Count];
+            Log.Info($"get router address: {self.RouterIndex - 1} {address}");
             string[] ss = address.Split(':');
             IPAddress ipAddress = IPAddress.Parse(ss[0]);
             if (self.RouterManagerIPAddress.AddressFamily == AddressFamily.InterNetworkV6)

+ 2 - 3
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterCheckComponentSystem.cs

@@ -52,7 +52,7 @@ namespace ET.Client
                     
                     Log.Info($"get recvLocalConn start: {root.Id} {realAddress} {localConn} {remoteConn}");
 
-                    (uint recvLocalConn, IPEndPoint routerAddress) = await RouterHelper.GetRouterAddress(netComponent, realAddress, localConn, remoteConn);
+                    (uint recvLocalConn, IPEndPoint routerAddress) = await netComponent.GetRouterAddress(realAddress, localConn, remoteConn);
                     if (recvLocalConn == 0)
                     {
                         Log.Error($"get recvLocalConn fail: {root.Id} {routerAddress} {realAddress} {localConn} {remoteConn}");
@@ -61,8 +61,7 @@ namespace ET.Client
                     
                     Log.Info($"get recvLocalConn ok: {root.Id} {routerAddress} {realAddress} {recvLocalConn} {localConn} {remoteConn}");
 
-                    realAddress = routerAddress;
-                    session.RemoteAddress = realAddress.ToString();
+                    session.RemoteAddress = routerAddress.ToString();
                     
                     session.LastRecvTime = TimeInfo.Instance.ClientNow();
                     

+ 4 - 2
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterHelper.cs

@@ -50,11 +50,13 @@ namespace ET.Client
             int count = 20;
             byte[] sendCache = new byte[512];
 
+            uint connectId = RandomGenerator.RandUInt32();
             sendCache.WriteTo(0, synFlag);
             sendCache.WriteTo(1, localConn);
             sendCache.WriteTo(5, remoteConn);
+            sendCache.WriteTo(9, connectId);
             byte[] addressBytes = realAddress.ToString().ToByteArray();
-            Array.Copy(addressBytes, 0, sendCache, 9, addressBytes.Length);
+            Array.Copy(addressBytes, 0, sendCache, 13, addressBytes.Length);
             TimerComponent timerComponent = netComponent.Fiber().TimerComponent;
             Log.Info($"router connect: {localConn} {remoteConn} {routerAddress} {realAddress}");
 
@@ -73,7 +75,7 @@ namespace ET.Client
 
                     lastSendTimer = timeNow;
                     // 发送
-                    routerConnector.Connect(sendCache, 0, addressBytes.Length + 9, routerAddress);
+                    routerConnector.Connect(sendCache, 0, addressBytes.Length + 13, routerAddress);
                 }
 
                 await timerComponent.WaitFrameAsync();

+ 24 - 13
Unity/Assets/Scripts/Hotfix/Server/Module/Router/RouterComponentSystem.cs

@@ -154,14 +154,15 @@ namespace ET.Server
             {
                 case KcpProtocalType.RouterReconnectSYN:
                 {
-                    if (messageLength < 9)
+                    if (messageLength < 13)
                     {
                         break;
                     }
 
                     uint outerConn = BitConverter.ToUInt32(self.Cache, 1);
                     uint innerConn = BitConverter.ToUInt32(self.Cache, 5);
-                    string realAddress = self.Cache.ToStr(9, messageLength - 9);
+                    uint connectId = BitConverter.ToUInt32(self.Cache, 9);
+                    string realAddress = self.Cache.ToStr(13, messageLength - 13);
 
                     RouterNode routerNode;
 
@@ -169,7 +170,7 @@ namespace ET.Server
                     if (!self.OuterNodes.TryGetValue(outerConn, out routerNode))
                     {
                         Log.Info($"router create reconnect: {self.IPEndPoint} {realAddress} {outerConn} {innerConn}");
-                        routerNode = self.New(realAddress, outerConn, innerConn, self.CloneAddress());
+                        routerNode = self.New(realAddress, outerConn, innerConn, connectId, self.CloneAddress());
                     }
                     
                     // 不是自己的,outerConn冲突, 直接break,也就是说这个软路由上有个跟自己outerConn冲突的连接,就不能连接了
@@ -186,13 +187,14 @@ namespace ET.Server
                         break;
                     }
 
-                    // 校验ip,连接过程中ip不能变化
-                    if (!Equals(routerNode.SyncIpEndPoint, self.IPEndPoint))
+                    // reconnect检查了InnerConn跟OuterConn,到这里肯定保证了是同一客户端, 如果connectid不一样,证明是两次不同的连接,可以删除老的连接
+                    if (routerNode.ConnectId != connectId)
                     {
-                        Log.Warning($"kcp router syn ip is diff1: {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}");
+                        Log.Warning($"kcp router router reconnect connectId diff, maybe router count too less: {connectId} {routerNode.ConnectId} {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}");
+                        self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterSame);
                         break;
                     }
-
+                    
                     // 校验内网地址
                     if (routerNode.InnerAddress != realAddress)
                     {
@@ -221,14 +223,15 @@ namespace ET.Server
                 }
                 case KcpProtocalType.RouterSYN:
                 {
-                    if (messageLength < 9)
+                    if (messageLength < 13)
                     {
                         break;
                     }
                     
                     uint outerConn = BitConverter.ToUInt32(self.Cache, 1);
                     uint innerConn = BitConverter.ToUInt32(self.Cache, 5);
-                    string realAddress = self.Cache.ToStr(9, messageLength - 9);
+                    uint connectId = BitConverter.ToUInt32(self.Cache, 9);
+                    string realAddress = self.Cache.ToStr(13, messageLength - 13);
 
                     // innerconn会在ack的时候赋值,所以routersync过程绝对是routerNode.InnerConn绝对是0
                     if (innerConn != 0)
@@ -240,7 +243,7 @@ namespace ET.Server
                     RouterNode routerNode;
                     if (!self.OuterNodes.TryGetValue(outerConn, out routerNode))
                     {
-                        routerNode = self.New(realAddress, outerConn, innerConn, self.CloneAddress());
+                        routerNode = self.New(realAddress, outerConn, innerConn, connectId, self.CloneAddress());
                         Log.Info($"router create: {realAddress} {outerConn} {innerConn} {routerNode.SyncIpEndPoint}");
                     }
 
@@ -256,7 +259,7 @@ namespace ET.Server
                         Log.Warning($"kcp router syn status InnerConn != 0: {outerConn} {innerConn} {routerNode.InnerConn}");
                         break;
                     }
-
+                    
                     if (++routerNode.RouterSyncCount > 40)
                     {
                         self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterRouterSyncCountTooMuchTimes);
@@ -269,6 +272,14 @@ namespace ET.Server
                         Log.Warning($"kcp router syn ip is diff1: {routerNode.SyncIpEndPoint} {self.IPEndPoint}");
                         break;
                     }
+                    
+                    // 这里因为InnerConn是0,无法保证连接是同一客户端发过来的,所以这里如果connectid不同,则break。注意逻辑跟reconnect不一样
+                    if (routerNode.ConnectId != connectId)
+                    {
+                        Log.Warning($"kcp router router connect connectId diff, maybe router count too less: {connectId} {routerNode.ConnectId} {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}");
+                        break;
+                    }
+
 
                     // 校验内网地址
                     if (routerNode.InnerAddress != realAddress)
@@ -580,12 +591,12 @@ namespace ET.Server
             return routerNode;
         }
 
-        private static RouterNode New(this RouterComponent self, string innerAddress, uint outerConn, uint innerConn, IPEndPoint syncEndPoint)
+        private static RouterNode New(this RouterComponent self, string innerAddress, uint outerConn, uint innerConn, uint connectId, IPEndPoint syncEndPoint)
         {
             RouterNode routerNode = self.AddChild<RouterNode>();
             routerNode.OuterConn = outerConn;
             routerNode.InnerConn = innerConn;
-
+            routerNode.ConnectId = connectId;
             routerNode.InnerIpEndPoint = NetworkHelper.ToIPEndPoint(innerAddress);
             routerNode.SyncIpEndPoint = syncEndPoint;
             routerNode.InnerAddress = innerAddress;

+ 1 - 0
Unity/Assets/Scripts/Model/Server/Module/Router/RouterNode.cs

@@ -18,6 +18,7 @@ namespace ET.Server
         public IKcpTransport KcpTransport;
         public uint OuterConn;
         public uint InnerConn;
+        public uint ConnectId;
         public long LastRecvOuterTime;
         public long LastRecvInnerTime;