using System;
using System.Collections.Generic;
using System.Net;
namespace BF
{
///
/// 单例
///
///
public sealed class NetClient
{
private readonly Dictionary channelServices = new Dictionary(new NetServiceTypeComparer());
private readonly Dictionary loopUpServiceDic = new Dictionary();
///
/// init reference count +1
/// shutdown reference count -1
/// if reference count less equals 0 will actually shutdown all service
///
private int referenceCount;
#region Instance
public static NetClient Instance
{
get { return Nested.instance; }
}
private NetClient()
{ }
private class Nested
{
internal static readonly NetClient instance = new NetClient();
static Nested()
{
}
}
#endregion
public void Init()
{
referenceCount++;
}
public void Start()
{
}
///
/// 关闭NetClient,会关闭所有连接,释放所有资源
///
public void Shutdown()
{
referenceCount--;
if (referenceCount > 0)
{
return;
}
foreach (var channelService in channelServices)
{
channelService.Value.Shutdown();
}
channelServices.Clear();
loopUpServiceDic.Clear();
}
public void SetupService(NetConfiguration configuration)
{
if (ContainChannelService(configuration.ServiceType))
{
return;
}
var service = CreateService(configuration);
channelServices.Add(service.ServiceType, service);
}
public void Connect(NetConnectConfiguration configuration, string domainName, int port)
{
if (loopUpServiceDic.ContainsKey(configuration.UniqueIdentifier))
{
return;
}
var service = GetChannelService(configuration.ServiceType);
service.Connect(configuration, domainName, port);
loopUpServiceDic.Add(configuration.UniqueIdentifier, service);
}
///
/// 创建新的连接,和Close是对应的概念
///
///
///
///
public void Connect(NetConnectConfiguration configuration, IPAddress ipAddress, int port)
{
if (loopUpServiceDic.ContainsKey(configuration.UniqueIdentifier))
{
return;
}
var service = GetChannelService(configuration.ServiceType);
service.Connect(configuration, ipAddress, port);
loopUpServiceDic.Add(configuration.UniqueIdentifier, service);
}
///
/// 手动开始重连,使用手动重连,必须关闭自动重连
///
///
public void Reconnect(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
service?.Reconnect(uniqueIdentifier);
}
///
/// 关闭Connect创建的连接,释放连接使用的资源;关闭后不可以再次使用此连接
///
///
public void Close(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
service?.Close(uniqueIdentifier);
loopUpServiceDic.Remove(uniqueIdentifier);
}
///
/// 暂时不公有
///
///
///
internal INetOutgoingMessage CreateMessage(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
return service?.CreateMessage(uniqueIdentifier);
}
///
/// 暂时不公有
///
///
///
internal NetSendResult Send(string uniqueIdentifier, INetOutgoingMessage message)
{
var service = GetChannelService(uniqueIdentifier);
return service.Send(uniqueIdentifier, message);
}
public NetSendResult Send(string uniqueIdentifier, uint group, byte cmd, byte[] data)
{
var service = GetChannelService(uniqueIdentifier);
return service.Send(uniqueIdentifier, group, cmd, data);
}
public INetIncomingMessage ReadMessage(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
return service?.ReadMessage(uniqueIdentifier);
}
public void RecycleMessage(string uniqueIdentifier, INetIncomingMessage message)
{
var service = GetChannelService(uniqueIdentifier);
service?.RecycleMessage(uniqueIdentifier, message);
}
public NetConnectStatus GetConnectStatus(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
if (service == null)
{
return NetConnectStatus.InvalidConnect;
}
return service.GetConnectStatus(uniqueIdentifier);
}
///
/// 获取指定连接的服务器地址
///
/// 连接id
/// 连接的远程服务器地址
public string GetConnectIP(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
if(service == null)
{
return string.Empty;
}
return service.GetConnectIP(uniqueIdentifier);
}
///
/// 获取指定连接的UGate服务器时间戳;此时间戳,是上一次心跳包同步的;
/// 注意:必须在连接状态下才可以获取到有效同步时间
///
/// 连接id
/// 由心跳包同步的UGate服务器时间戳
public long GetServerTimestamp(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
if(service == null)
{
return 0;
}
return service.GetConnectServerTimestamp(uniqueIdentifier);
}
private bool ContainChannelService(NetServiceType serviceType)
{
return channelServices.ContainsKey(serviceType);
}
private INetChannelService GetChannelService(NetServiceType serviceType)
{
if (!channelServices.TryGetValue(serviceType, out INetChannelService service))
{
throw new NotImplementedException($"{serviceType} not support.");
}
return service;
}
private INetChannelService GetChannelService(string uniqueIdentifier)
{
if (!loopUpServiceDic.TryGetValue(uniqueIdentifier, out INetChannelService service))
{
return null;
}
return service;
}
private INetChannelService CreateService(NetConfiguration configuration)
{
INetChannelService service = null;
switch (configuration.ServiceType)
{
case NetServiceType.TCPService:
service = new TCPChannelService();
break;
case NetServiceType.UDPService:
throw new NotImplementedException();
case NetServiceType.WebsocketService:
throw new NotImplementedException();
default:
throw new NotImplementedException();
}
service.Start(configuration);
return service;
}
}
}