RouterHelper.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. namespace ET.Client
  5. {
  6. public static class RouterHelper
  7. {
  8. // 注册router
  9. public static async ETTask<Session> CreateRouterSession(Scene clientScene, IPEndPoint address)
  10. {
  11. (uint recvLocalConn, IPEndPoint routerAddress) = await GetRouterAddress(clientScene, address, 0, 0);
  12. if (recvLocalConn == 0)
  13. {
  14. throw new Exception($"get router fail: {clientScene.Id} {address}");
  15. }
  16. Log.Info($"get router: {recvLocalConn} {routerAddress}");
  17. Session routerSession = clientScene.GetComponent<NetClientComponent>().Create(routerAddress, address, recvLocalConn);
  18. routerSession.AddComponent<PingComponent>();
  19. routerSession.AddComponent<RouterCheckComponent>();
  20. return routerSession;
  21. }
  22. public static async ETTask<(uint, IPEndPoint)> GetRouterAddress(Scene clientScene, IPEndPoint address, uint localConn, uint remoteConn)
  23. {
  24. Log.Info($"start get router address: {clientScene.Id} {address} {localConn} {remoteConn}");
  25. //return (RandomHelper.RandUInt32(), address);
  26. RouterAddressComponent routerAddressComponent = clientScene.GetComponent<RouterAddressComponent>();
  27. IPEndPoint routerInfo = routerAddressComponent.GetAddress();
  28. uint recvLocalConn = await Connect(routerInfo, address, localConn, remoteConn);
  29. Log.Info($"finish get router address: {clientScene.Id} {address} {localConn} {remoteConn} {recvLocalConn} {routerInfo}");
  30. return (recvLocalConn, routerInfo);
  31. }
  32. // 向router申请
  33. private static async ETTask<uint> Connect(IPEndPoint routerAddress, IPEndPoint realAddress, uint localConn, uint remoteConn)
  34. {
  35. uint connectId = RandomGenerator.RandUInt32();
  36. using Socket socket = new Socket(routerAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
  37. int count = 20;
  38. byte[] sendCache = new byte[512];
  39. byte[] recvCache = new byte[512];
  40. uint synFlag = localConn == 0? KcpProtocalType.RouterSYN : KcpProtocalType.RouterReconnectSYN;
  41. sendCache.WriteTo(0, synFlag);
  42. sendCache.WriteTo(1, localConn);
  43. sendCache.WriteTo(5, remoteConn);
  44. sendCache.WriteTo(9, connectId);
  45. byte[] addressBytes = realAddress.ToString().ToByteArray();
  46. Array.Copy(addressBytes, 0, sendCache, 13, addressBytes.Length);
  47. Log.Info($"router connect: {connectId} {localConn} {remoteConn} {routerAddress} {realAddress}");
  48. EndPoint recvIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
  49. long lastSendTimer = 0;
  50. while (true)
  51. {
  52. long timeNow = TimeHelper.ClientFrameTime();
  53. if (timeNow - lastSendTimer > 300)
  54. {
  55. if (--count < 0)
  56. {
  57. Log.Error($"router connect timeout fail! {localConn} {remoteConn} {routerAddress} {realAddress}");
  58. return 0;
  59. }
  60. lastSendTimer = timeNow;
  61. // 发送
  62. socket.SendTo(sendCache, 0, addressBytes.Length + 13, SocketFlags.None, routerAddress);
  63. }
  64. await TimerComponent.Instance.WaitFrameAsync();
  65. // 接收
  66. if (socket.Available > 0)
  67. {
  68. int messageLength = socket.ReceiveFrom(recvCache, ref recvIPEndPoint);
  69. if (messageLength != 9)
  70. {
  71. Log.Error($"router connect error1: {connectId} {messageLength} {localConn} {remoteConn} {routerAddress} {realAddress}");
  72. continue;
  73. }
  74. byte flag = recvCache[0];
  75. if (flag != KcpProtocalType.RouterReconnectACK && flag != KcpProtocalType.RouterACK)
  76. {
  77. Log.Error($"router connect error2: {connectId} {synFlag} {flag} {localConn} {remoteConn} {routerAddress} {realAddress}");
  78. continue;
  79. }
  80. uint recvRemoteConn = BitConverter.ToUInt32(recvCache, 1);
  81. uint recvLocalConn = BitConverter.ToUInt32(recvCache, 5);
  82. Log.Info($"router connect finish: {connectId} {recvRemoteConn} {recvLocalConn} {localConn} {remoteConn} {routerAddress} {realAddress}");
  83. return recvLocalConn;
  84. }
  85. }
  86. }
  87. }
  88. }