using System; using System.Collections.Generic; using System.Net.Sockets; using System.Threading.Tasks; using System.Linq; using Ultron.Proxy.Models; using Ultron.Proxy.Utils; namespace Ultron.Proxy { public class ClientGroupEventArgs : EventArgs { public IEnumerable NewClients; public ClientIdAppId App; } public class ServerConnnectionManager { private int MAX_CONNECT_SIZE = 6;//magic value,单个应用最大连接数,有些应用端支持多连接,需要调高此值,当该值较大时,此值会增加 private int ClientID = 0; private ServerConnnectionManager() { Router.Logger.Debug("ServerConnnectionManager initialized."); } /// /// 初始化配置,返回服务端返回的配置 /// /// public async Task InitConfig() { ClientModel clientModel = await ReadConfigFromProvider(); //要求服务端分配资源并获取服务端配置,待完善 this.ClientID = clientModel.ClientId; //分配appid给不同的Client ServiceClientListCollection = new Dictionary(); for (int i = 0; i < clientModel.AppList.Count; i++) { var app = clientModel.AppList[i]; ServiceClientListCollection.Add(clientModel.AppList[i].AppId, new ClientAppWorker() { AppId = app.AppId, Port = app.Port, TcpClientGroup = new List(MAX_CONNECT_SIZE) }); } return clientModel; } /// /// 从服务端读取配置 /// /// private async Task ReadConfigFromProvider() { //《c#并发编程经典实例》 9.3 超时后取消 var config = Router.ClientConfig; Router.Logger.Debug("Reading Config From Provider.."); TcpClient configClient = new TcpClient(); var delayDispose = Task.Delay(TimeSpan.FromSeconds(600)).ContinueWith(_ => configClient.Dispose()); var connectAsync = configClient.ConnectAsync(config.ProviderAddress, config.ProviderConfigPort); //超时则dispose掉 var comletedTask = await Task.WhenAny(delayDispose, connectAsync); if (!connectAsync.IsCompleted) { throw new Exception("连接超时"); } var configStream = configClient.GetStream(); //请求1 端口数 var requestBytes = new ClientNewAppRequest { ClientId = 0, ClientCount = config.Clients.Count(obj => obj.AppID == 0) //appid为0的则是未分配的 }.ToBytes(); await configStream.WriteAsync(requestBytes, 0, requestBytes.Length); //请求2 分配端口 //var requestBytes byte[] requestBytes2 = new byte[config.Clients.Count * 2]; int i = 0; foreach (var client in config.Clients) { byte[] portBytes = StringUtil.IntTo2Bytes(client.RemotePort); requestBytes2[2 * i] = portBytes[0]; requestBytes2[2 * i + 1] = portBytes[1]; i++; } await configStream.WriteAsync(requestBytes2, 0, requestBytes2.Length); //读端口配置 byte[] serverConfig = new byte[256]; int readBytesCount = await configStream.ReadAsync(serverConfig, 0, serverConfig.Length); if (readBytesCount == 0) Router.Logger.Debug("服务器状态异常,已断开连接"); return ClientModel.GetFromBytes(serverConfig, readBytesCount); } /// /// clients Connected event. /// public event EventHandler ClientGroupConnected; /// /// 将所有的app循环连接服务端 /// /// public async Task PollingToProvider() { var config = Router.ClientConfig; if (ClientID == 0) { Router.Logger.Debug("error:未连接客户端"); return; }; //int hungryNumber = MAX_CONNECT_SIZE / 2; byte[] clientBytes = StringUtil.IntTo2Bytes(ClientID); List taskList = new List(); foreach (var kv in ServiceClientListCollection) { int appid = kv.Key; await ConnectAppToServer(appid); } } public async Task ConnectAppToServer(int appid) { var app = this.ServiceClientListCollection[appid]; var config = Router.ClientConfig; // ClientAppWorker app = kv.Value; byte[] requestBytes = StringUtil.ClientIDAppIdToBytes(ClientID, appid); var clientList = new List(); //补齐 TcpClient client = new TcpClient(); await client.ConnectAsync(config.ProviderAddress, config.ProviderPort); //连完了马上发送端口信息过去,方便服务端分配 await client.GetStream().WriteAsync(requestBytes, 0, requestBytes.Length); Router.Logger.Debug("ClientID:" + ClientID.ToString() + " AppId:" + appid.ToString() + " 已连接"); app.TcpClientGroup.Add(client); clientList.Add(client); //var clientList = new List() { client }; ClientGroupConnected(this, new ClientGroupEventArgs() { NewClients = clientList, App = new ClientIdAppId { ClientId = ClientID, AppId = appid } }); } //key:appid value;ClientApp public Dictionary ServiceClientListCollection;// = new Dictionary>(); //private static ServerConnnectionManager Instance = new Lazy(() => new ServerConnnectionManager()).Value; public static ServerConnnectionManager Create() { return new ServerConnnectionManager(); } public TcpClient RemoveClient(int appId, TcpClient client) { if (ServiceClientListCollection[appId].TcpClientGroup.Remove(client)) return client; else { throw new Exception("无此client"); } } } }