Ultron.Proxy/Ultron.Proxy.Client/ServerConnnectionManager.cs

179 lines
6.6 KiB
C#

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<TcpClient> 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.");
}
/// <summary>
/// 初始化配置,返回服务端返回的配置
/// </summary>
/// <returns></returns>
public async Task<ClientModel> InitConfig()
{
ClientModel clientModel = await ReadConfigFromProvider();
//要求服务端分配资源并获取服务端配置,待完善
this.ClientID = clientModel.ClientId;
//分配appid给不同的Client
ServiceClientListCollection = new Dictionary<int, ClientAppWorker>();
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<TcpClient>(MAX_CONNECT_SIZE)
});
}
return clientModel;
}
/// <summary>
/// 从服务端读取配置
/// </summary>
/// <returns></returns>
private async Task<ClientModel> 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);
}
/// <summary>
/// clients Connected event.
/// </summary>
public event EventHandler ClientGroupConnected;
/// <summary>
/// 将所有的app循环连接服务端
/// </summary>
/// <returns></returns>
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<Task> taskList = new List<Task>();
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>();
//补齐
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<TcpClient>() { client };
ClientGroupConnected(this, new ClientGroupEventArgs()
{
NewClients = clientList,
App = new ClientIdAppId
{
ClientId = ClientID,
AppId = appid
}
});
}
//key:appid value;ClientApp
public Dictionary<int, ClientAppWorker> ServiceClientListCollection;// = new Dictionary<int, List<TcpClient>>();
//private static ServerConnnectionManager Instance = new Lazy<ServerConnnectionManager>(() => 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");
}
}
}
}