179 lines
6.6 KiB
C#
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");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|