RouterHelper.cs 4.7 KB

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