mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
[+] 接入ET8服务端
[+] 接入ET8服务端
This commit is contained in:
@@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c6ca4a5394922f488127ebb53362456
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 567a551c7abf2fd4c9b592af991b609e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55f4125eddb1aa543bfdce8f42b4d5f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c76c4f4f2b0cbc5458c3a39c18717d31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user