[+] 接入ET8服务端

[+] 接入ET8服务端
This commit is contained in:
ALEXTANG
2023-07-13 12:23:48 +08:00
parent e0be062006
commit 336d4b2eb9
1316 changed files with 130657 additions and 626 deletions

View File

@@ -0,0 +1,25 @@
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
namespace ET.Client
{
public static partial class HttpClientHelper
{
public static async ETTask<string> Get(string link)
{
try
{
using HttpClient httpClient = new();
HttpResponseMessage response = await httpClient.GetAsync(link);
string result = await response.Content.ReadAsStringAsync();
return result;
}
catch (Exception e)
{
throw new Exception($"http request fail: {link.Substring(0,link.IndexOf('?'))}\n{e}");
}
}
}
}

View File

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

View File

@@ -0,0 +1,82 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace ET.Client
{
[EntitySystemOf(typeof(RouterAddressComponent))]
[FriendOf(typeof(RouterAddressComponent))]
public static partial class RouterAddressComponentSystem
{
[EntitySystem]
private static void Awake(this RouterAddressComponent self, string address, int port)
{
self.RouterManagerHost = address;
self.RouterManagerPort = port;
}
public static async ETTask Init(this RouterAddressComponent self)
{
self.RouterManagerIPAddress = NetworkHelper.GetHostAddress(self.RouterManagerHost);
await self.GetAllRouter();
}
private static async ETTask GetAllRouter(this RouterAddressComponent self)
{
string url = $"http://{self.RouterManagerHost}:{self.RouterManagerPort}/get_router?v={RandomGenerator.RandUInt32()}";
Log.Debug($"start get router info: {url}");
string routerInfo = await HttpClientHelper.Get(url);
Log.Debug($"recv router info: {routerInfo}");
HttpGetRouterResponse httpGetRouterResponse = MongoHelper.FromJson<HttpGetRouterResponse>(routerInfo);
self.Info = httpGetRouterResponse;
Log.Debug($"start get router info finish: {MongoHelper.ToJson(httpGetRouterResponse)}");
// 打乱顺序
RandomGenerator.BreakRank(self.Info.Routers);
self.WaitTenMinGetAllRouter().Coroutine();
}
// 等10分钟再获取一次
public static async ETTask WaitTenMinGetAllRouter(this RouterAddressComponent self)
{
await self.Fiber().TimerComponent.WaitAsync(5 * 60 * 1000);
if (self.IsDisposed)
{
return;
}
await self.GetAllRouter();
}
public static IPEndPoint GetAddress(this RouterAddressComponent self)
{
if (self.Info.Routers.Count == 0)
{
return null;
}
string address = self.Info.Routers[self.RouterIndex++ % self.Info.Routers.Count];
string[] ss = address.Split(':');
IPAddress ipAddress = IPAddress.Parse(ss[0]);
if (self.RouterManagerIPAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
ipAddress = ipAddress.MapToIPv6();
}
return new IPEndPoint(ipAddress, int.Parse(ss[1]));
}
public static IPEndPoint GetRealmAddress(this RouterAddressComponent self, string account)
{
int v = account.Mode(self.Info.Realms.Count);
string address = self.Info.Realms[v];
string[] ss = address.Split(':');
IPAddress ipAddress = IPAddress.Parse(ss[0]);
//if (self.IPAddress.AddressFamily == AddressFamily.InterNetworkV6)
//{
// ipAddress = ipAddress.MapToIPv6();
//}
return new IPEndPoint(ipAddress, int.Parse(ss[1]));
}
}
}

View File

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

View File

@@ -0,0 +1,71 @@
using System;
using System.Net;
namespace ET.Client
{
[EntitySystemOf(typeof(RouterCheckComponent))]
public static partial class RouterCheckComponentSystem
{
[EntitySystem]
private static void Awake(this RouterCheckComponent self)
{
self.CheckAsync().Coroutine();
}
private static async ETTask CheckAsync(this RouterCheckComponent self)
{
Session session = self.GetParent<Session>();
long instanceId = self.InstanceId;
Fiber fiber = self.Fiber();
Scene root = fiber.Root;
while (true)
{
if (self.InstanceId != instanceId)
{
return;
}
await fiber.TimerComponent.WaitAsync(1000);
if (self.InstanceId != instanceId)
{
return;
}
long time = self.Fiber().TimeInfo.ClientFrameTime();
if (time - session.LastRecvTime < 7 * 1000)
{
continue;
}
try
{
long sessionId = session.Id;
(uint localConn, uint remoteConn) = session.AService.GetChannelConn(sessionId);
IPEndPoint realAddress = self.GetParent<Session>().RemoteAddress;
Log.Info($"get recvLocalConn start: {root.Id} {realAddress} {localConn} {remoteConn}");
(uint recvLocalConn, IPEndPoint routerAddress) = await RouterHelper.GetRouterAddress(root, realAddress, localConn, remoteConn);
if (recvLocalConn == 0)
{
Log.Error($"get recvLocalConn fail: {root.Id} {routerAddress} {realAddress} {localConn} {remoteConn}");
continue;
}
Log.Info($"get recvLocalConn ok: {root.Id} {routerAddress} {realAddress} {recvLocalConn} {localConn} {remoteConn}");
session.LastRecvTime = self.Fiber().TimeInfo.ClientNow();
session.AService.ChangeAddress(sessionId, routerAddress);
}
catch (Exception e)
{
Log.Error(e);
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,109 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace ET.Client
{
public static partial class RouterHelper
{
// 注册router
public static async ETTask<Session> CreateRouterSession(Scene root, IPEndPoint address)
{
(uint recvLocalConn, IPEndPoint routerAddress) = await GetRouterAddress(root, address, 0, 0);
if (recvLocalConn == 0)
{
throw new Exception($"get router fail: {root.Id} {address}");
}
Log.Info($"get router: {recvLocalConn} {routerAddress}");
Session routerSession = root.GetComponent<NetClientComponent>().Create(routerAddress, address, recvLocalConn);
routerSession.AddComponent<PingComponent>();
routerSession.AddComponent<RouterCheckComponent>();
return routerSession;
}
public static async ETTask<(uint, IPEndPoint)> GetRouterAddress(Scene root, IPEndPoint address, uint localConn, uint remoteConn)
{
Log.Info($"start get router address: {root.Id} {address} {localConn} {remoteConn}");
//return (RandomHelper.RandUInt32(), address);
RouterAddressComponent routerAddressComponent = root.GetComponent<RouterAddressComponent>();
IPEndPoint routerInfo = routerAddressComponent.GetAddress();
uint recvLocalConn = await Connect(root, routerInfo, address, localConn, remoteConn);
Log.Info($"finish get router address: {root.Id} {address} {localConn} {remoteConn} {recvLocalConn} {routerInfo}");
return (recvLocalConn, routerInfo);
}
// 向router申请
private static async ETTask<uint> Connect(Scene root, IPEndPoint routerAddress, IPEndPoint realAddress, uint localConn, uint remoteConn)
{
uint connectId = RandomGenerator.RandUInt32();
using Socket socket = new Socket(routerAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
int count = 20;
byte[] sendCache = new byte[512];
byte[] recvCache = new byte[512];
uint synFlag = localConn == 0? KcpProtocalType.RouterSYN : KcpProtocalType.RouterReconnectSYN;
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, 13, addressBytes.Length);
Log.Info($"router connect: {connectId} {localConn} {remoteConn} {routerAddress} {realAddress}");
EndPoint recvIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
long lastSendTimer = 0;
Fiber fiber = root.Fiber;
while (true)
{
long timeNow = fiber.TimeInfo.ClientFrameTime();
if (timeNow - lastSendTimer > 300)
{
if (--count < 0)
{
Log.Error($"router connect timeout fail! {localConn} {remoteConn} {routerAddress} {realAddress}");
return 0;
}
lastSendTimer = timeNow;
// 发送
socket.SendTo(sendCache, 0, addressBytes.Length + 13, SocketFlags.None, routerAddress);
}
await fiber.TimerComponent.WaitFrameAsync();
// 接收
if (socket.Available > 0)
{
int messageLength = socket.ReceiveFrom(recvCache, ref recvIPEndPoint);
if (messageLength != 9)
{
Log.Error($"router connect error1: {connectId} {messageLength} {localConn} {remoteConn} {routerAddress} {realAddress}");
continue;
}
byte flag = recvCache[0];
if (flag != KcpProtocalType.RouterReconnectACK && flag != KcpProtocalType.RouterACK)
{
Log.Error($"router connect error2: {connectId} {synFlag} {flag} {localConn} {remoteConn} {routerAddress} {realAddress}");
continue;
}
uint recvRemoteConn = BitConverter.ToUInt32(recvCache, 1);
uint recvLocalConn = BitConverter.ToUInt32(recvCache, 5);
Log.Info($"router connect finish: {connectId} {recvRemoteConn} {recvLocalConn} {localConn} {remoteConn} {routerAddress} {realAddress}");
return recvLocalConn;
}
}
}
}
}

View File

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