2023-04-03 11:04:31 +08:00

271 lines
8.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Net;
namespace BF
{
/// <summary>
/// 单例
///
/// </summary>
public sealed class NetClient
{
private readonly Dictionary<NetServiceType, INetChannelService> channelServices = new Dictionary<NetServiceType, INetChannelService>(new NetServiceTypeComparer());
private readonly Dictionary<string, INetChannelService> loopUpServiceDic = new Dictionary<string, INetChannelService>();
/// <summary>
/// init reference count +1
/// shutdown reference count -1
/// if reference count less equals 0 will actually shutdown all service
/// </summary>
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()
{
}
/// <summary>
/// 关闭NetClient会关闭所有连接释放所有资源
/// </summary>
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);
}
/// <summary>
/// 创建新的连接和Close是对应的概念
/// </summary>
/// <param name="configuration"></param>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
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);
}
/// <summary>
/// 手动开始重连,使用手动重连,必须关闭自动重连
/// </summary>
/// <param name="uniqueIdentifier"></param>
public void Reconnect(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
service?.Reconnect(uniqueIdentifier);
}
/// <summary>
/// 关闭Connect创建的连接释放连接使用的资源关闭后不可以再次使用此连接
/// </summary>
/// <param name="uniqueIdentifier"></param>
public void Close(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
service?.Close(uniqueIdentifier);
loopUpServiceDic.Remove(uniqueIdentifier);
}
/// <summary>
/// 暂时不公有
/// </summary>
/// <param name="uniqueIdentifier"></param>
/// <returns></returns>
internal INetOutgoingMessage CreateMessage(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
return service?.CreateMessage(uniqueIdentifier);
}
/// <summary>
/// 暂时不公有
/// </summary>
/// <param name="uniqueIdentifier"></param>
/// <returns></returns>
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);
}
/// <summary>
/// 获取指定连接的服务器地址
/// </summary>
/// <param name="uniqueIdentifier">连接id</param>
/// <returns>连接的远程服务器地址</returns>
public string GetConnectIP(string uniqueIdentifier)
{
var service = GetChannelService(uniqueIdentifier);
if(service == null)
{
return string.Empty;
}
return service.GetConnectIP(uniqueIdentifier);
}
/// <summary>
/// 获取指定连接的UGate服务器时间戳此时间戳是上一次心跳包同步的
/// 注意:必须在连接状态下才可以获取到有效同步时间
/// </summary>
/// <param name="uniqueIdentifier">连接id</param>
/// <returns>由心跳包同步的UGate服务器时间戳</returns>
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;
}
}
}