Explorar el Código

简化Router Connect代码,使用KService的Transport去连接Router

tanghai hace 2 años
padre
commit
25965c8bc8

+ 24 - 1
Unity/Assets/Scripts/Core/Network/KService.cs

@@ -110,6 +110,18 @@ namespace ET
 #else
         public readonly ArrayPool<byte> byteArrayPool = ArrayPool<byte>.Create(2048,200);
 #endif
+
+        private readonly Dictionary<uint, Action<byte, uint, uint>> routerAckCallback = new();
+
+        public void AddRouterAckCallback(uint id, Action<byte, uint, uint> action)
+        {
+            this.routerAckCallback.Add(id, action);
+        }
+        
+        public void RemoveRouterAckCallback(uint id)
+        {
+            this.routerAckCallback.Remove(id);
+        }
         
         public override bool IsDisposed()
         {
@@ -175,12 +187,23 @@ namespace ET
                 // conn从100开始,如果为1,2,3则是特殊包
                 uint remoteConn = 0;
                 uint localConn = 0;
-                
                 try
                 {
                     KChannel kChannel = null;
                     switch (flag)
                     {
+                        case KcpProtocalType.RouterACK:
+                        case KcpProtocalType.RouterReconnectACK:
+                        {
+                            remoteConn = BitConverter.ToUInt32(this.cache, 1);
+                            localConn = BitConverter.ToUInt32(this.cache, 5);
+
+                            if (this.routerAckCallback.TryGetValue(localConn, out var action))
+                            {
+                                action.Invoke(flag, localConn, remoteConn);
+                            }
+                            break;
+                        }
                         case KcpProtocalType.RouterReconnectSYN:
                         {
                             // 长度!=5,不是RouterReconnectSYN消息

+ 37 - 0
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterConnectorSystem.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Net;
+
+namespace ET.Client
+{
+    [FriendOf(typeof(RouterConnector))]
+    [EntitySystemOf(typeof(RouterConnector))]
+    public static partial class RouterConnectorSystem
+    {
+        [EntitySystem]
+        private static void Awake(this RouterConnector self)
+        {
+            NetComponent netComponent = self.GetParent<NetComponent>();
+            KService kService = (KService)netComponent.AService;
+            kService.AddRouterAckCallback((uint)self.Id, (flag, local, remote) =>
+            {
+                self.Flag = flag;
+                self.LocalConn = local;
+                self.RemoteConn = remote;
+            });
+        }
+        [EntitySystem]
+        private static void Destroy(this RouterConnector self)
+        {
+            NetComponent netComponent = self.GetParent<NetComponent>();
+            KService kService = (KService)netComponent.AService;
+            kService.RemoveRouterAckCallback((uint)self.Id);
+        }
+
+        public static void Connect(this RouterConnector self, byte[] bytes, int index, int length, IPEndPoint ipEndPoint)
+        {
+            NetComponent netComponent = self.GetParent<NetComponent>();
+            KService kService = (KService)netComponent.AService;
+            kService.Transport.Send(bytes, index, length, ipEndPoint);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterConnectorSystem.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3a76ed65ff9af4c40bb9ef5ea9a68b25
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 39 - 79
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterHelper.cs

@@ -41,96 +41,56 @@ namespace ET.Client
         // 向router申请
         private static async ETTask<uint> Connect(NetComponent netComponent, IPEndPoint routerAddress, IPEndPoint realAddress, uint localConn, uint remoteConn)
         {
-            IKcpTransport iKcpTransport = null;
-            try
+            uint synFlag;
+            if (localConn == 0)
             {
-                NetworkProtocol protocol = ((KService)netComponent.AService).Protocol;
-                switch (protocol)
-                {
-                    case NetworkProtocol.TCP:
-                        iKcpTransport = new TcpTransport(routerAddress.AddressFamily);
-                        break;
-                    case NetworkProtocol.UDP:
-                        iKcpTransport = new UdpTransport(routerAddress.AddressFamily);
-                        break;
-                    default:
-                        throw new ArgumentOutOfRangeException();
-                }
-
-                int count = 20;
-                byte[] sendCache = new byte[512];
-                byte[] recvCache = new byte[512];
-
-                uint synFlag;
-                if (localConn == 0)
-                {
-                    synFlag = KcpProtocalType.RouterSYN;
-                    localConn = RandomGenerator.RandUInt32();
-                }
-                else
-                {
-                    synFlag = KcpProtocalType.RouterReconnectSYN;
-                }
+                synFlag = KcpProtocalType.RouterSYN;
+                localConn = RandomGenerator.RandUInt32();
+            }
+            else
+            {
+                synFlag = KcpProtocalType.RouterReconnectSYN;
+            }
 
-                sendCache.WriteTo(0, synFlag);
-                sendCache.WriteTo(1, localConn);
-                sendCache.WriteTo(5, remoteConn);
-                byte[] addressBytes = realAddress.ToString().ToByteArray();
-                Array.Copy(addressBytes, 0, sendCache, 9, addressBytes.Length);
-                Fiber fiber = netComponent.Fiber();
-                Log.Info($"router connect: {localConn} {remoteConn} {routerAddress} {realAddress}");
+            using RouterConnector routerConnector = netComponent.AddChildWithId<RouterConnector>(localConn);
+            
+            int count = 20;
+            byte[] sendCache = new byte[512];
 
-                EndPoint recvIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
+            sendCache.WriteTo(0, synFlag);
+            sendCache.WriteTo(1, localConn);
+            sendCache.WriteTo(5, remoteConn);
+            byte[] addressBytes = realAddress.ToString().ToByteArray();
+            Array.Copy(addressBytes, 0, sendCache, 9, addressBytes.Length);
+            TimerComponent timerComponent = netComponent.Fiber().TimerComponent;
+            Log.Info($"router connect: {localConn} {remoteConn} {routerAddress} {realAddress}");
 
-                long lastSendTimer = 0;
+            long lastSendTimer = 0;
 
-                while (true)
+            while (true)
+            {
+                long timeNow = TimeInfo.Instance.ClientFrameTime();
+                if (timeNow - lastSendTimer > 300)
                 {
-                    iKcpTransport.Update();
-                    
-                    long timeNow = TimeInfo.Instance.ClientFrameTime();
-                    if (timeNow - lastSendTimer > 300)
+                    if (--count < 0)
                     {
-                        if (--count < 0)
-                        {
-                            Log.Error($"router connect timeout fail! {localConn} {remoteConn} {routerAddress} {realAddress}");
-                            return 0;
-                        }
-
-                        lastSendTimer = timeNow;
-                        // 发送
-                        iKcpTransport.Send(sendCache, 0, addressBytes.Length + 9, routerAddress);
+                        Log.Error($"router connect timeout fail! {localConn} {remoteConn} {routerAddress} {realAddress}");
+                        return 0;
                     }
 
-                    await fiber.TimerComponent.WaitFrameAsync();
-                    
-                    // 接收
-                    if (iKcpTransport.Available() > 0)
-                    {
-                        int messageLength = iKcpTransport.Recv(recvCache, ref recvIPEndPoint);
-                        if (messageLength != 9)
-                        {
-                            Log.Error($"router connect error1: {messageLength} {localConn} {remoteConn} {routerAddress} {realAddress}");
-                            continue;
-                        }
-
-                        byte flag = recvCache[0];
-                        if (flag != KcpProtocalType.RouterReconnectACK && flag != KcpProtocalType.RouterACK)
-                        {
-                            Log.Error($"router connect error2: {synFlag} {flag} {localConn} {remoteConn} {routerAddress} {realAddress}");
-                            continue;
-                        }
+                    lastSendTimer = timeNow;
+                    // 发送
+                    routerConnector.Connect(sendCache, 0, addressBytes.Length + 9, routerAddress);
+                }
 
-                        uint recvRemoteConn = BitConverter.ToUInt32(recvCache, 1);
-                        uint recvLocalConn = BitConverter.ToUInt32(recvCache, 5);
-                        Log.Info($"router connect finish: {recvRemoteConn} {recvLocalConn} {localConn} {remoteConn} {routerAddress} {realAddress}");
-                        return recvLocalConn;
-                    }
+                await timerComponent.WaitFrameAsync();
+                
+                if (routerConnector.LocalConn != localConn || routerConnector.RemoteConn != remoteConn)
+                {
+                    continue;
                 }
-            }
-            finally
-            {
-                iKcpTransport?.Dispose();
+
+                return routerConnector.LocalConn;
             }
         }
     }

+ 21 - 3
Unity/Assets/Scripts/Hotfix/Server/Module/Router/RouterComponentSystem.cs

@@ -225,20 +225,38 @@ namespace ET.Server
                     {
                         break;
                     }
-
+                    
                     uint outerConn = BitConverter.ToUInt32(self.Cache, 1);
                     uint innerConn = BitConverter.ToUInt32(self.Cache, 5);
                     string realAddress = self.Cache.ToStr(9, messageLength - 9);
 
+                    // innerconn会在ack的时候赋值,所以routersync过程绝对是routerNode.InnerConn绝对是0
+                    if (innerConn != 0)
+                    {
+                        Log.Warning($"kcp router syn status innerConn != 0: {outerConn} {innerConn}");
+                        break;
+                    }
+                    
                     RouterNode routerNode;
-
                     if (!self.OuterNodes.TryGetValue(outerConn, out routerNode))
                     {
-                        outerConn = NetServices.Instance.CreateConnectChannelId();
                         routerNode = self.New(realAddress, outerConn, innerConn, self.CloneAddress());
                         Log.Info($"router create: {realAddress} {outerConn} {innerConn} {routerNode.SyncIpEndPoint}");
                     }
 
+                    if (routerNode.Status != RouterStatus.Sync)
+                    {
+                        Log.Warning($"kcp router syn status error: {outerConn} {innerConn} {routerNode.InnerConn}");
+                        break;
+                    }
+
+                    // innerconn会在ack的时候赋值,所以routersync过程绝对是routerNode.InnerConn绝对是0
+                    if (routerNode.InnerConn != innerConn)
+                    {
+                        Log.Warning($"kcp router syn status InnerConn != 0: {outerConn} {innerConn} {routerNode.InnerConn}");
+                        break;
+                    }
+
                     if (++routerNode.RouterSyncCount > 40)
                     {
                         self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterRouterSyncCountTooMuchTimes);

+ 10 - 0
Unity/Assets/Scripts/Model/Client/Demo/NetClient/Router/RouterConnector.cs

@@ -0,0 +1,10 @@
+namespace ET.Client
+{
+    [ChildOf(typeof(NetComponent))]
+    public class RouterConnector: Entity, IAwake, IDestroy
+    {
+        public byte Flag { get; set; }
+        public uint LocalConn { get; set; }
+        public uint RemoteConn { get; set; }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Model/Client/Demo/NetClient/Router/RouterConnector.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 08580776b4d87f149876a786db80a2bf
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: