//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
// CSDN博客:https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频:https://space.bilibili.com/94253567
// Gitee源代码仓库:https://gitee.com/RRQM_Home
// Github源代码仓库:https://github.com/RRQM
// API首页:https://www.yuque.com/rrqm/touchsocket/index
// 交流QQ群:234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using TouchSocket.Core;
using TouchSocket.Resources;
namespace TouchSocket.Sockets
{
///
/// TCP泛型服务器,由客户自己指定类型。
///
public class TcpService : TcpServiceBase, ITcpService where TClient : SocketClient
{
///
/// 构造函数
///
public TcpService()
{
m_socketClients = new SocketClientCollection();
m_getDefaultNewID = () =>
{
return Interlocked.Increment(ref m_nextId).ToString();
};
}
#region 变量
private readonly SocketClientCollection m_socketClients;
private int m_backlog;
private TouchSocketConfig m_config;
private Func m_getDefaultNewID;
private int m_maxCount;
private NetworkMonitor[] m_monitors;
private long m_nextId;
private ReceiveType m_receiveType;
private ServerState m_serverState;
private bool m_usePlugin;
private bool m_useSsl;
#endregion 变量
#region 属性
///
/// 获取服务器配置
///
public override TouchSocketConfig Config => m_config;
///
///
///
public override IContainer Container => Config?.Container;
///
///
///
public override Func GetDefaultNewID => m_getDefaultNewID;
///
///
///
public override int MaxCount => m_maxCount;
///
///
///
public override NetworkMonitor[] Monitors => m_monitors;
///
///
///
public override IPluginsManager PluginsManager => Config?.PluginsManager;
///
///
///
public override string ServerName => Config?.GetValue(TouchSocketConfigExtension.ServerNameProperty);
///
///
///
public override ServerState ServerState => m_serverState;
///
///
///
public override SocketClientCollection SocketClients => m_socketClients;
///
///
///
public override bool UsePlugin => m_usePlugin;
///
///
///
public override bool UseSsl => m_useSsl;
#endregion 属性
#region 事件
///
/// 用户连接完成
///
public TouchSocketEventHandler Connected { get; set; }
///
/// 有用户连接的时候
///
public OperationEventHandler Connecting { get; set; }
///
/// 有用户断开连接
///
public DisconnectEventHandler Disconnected { get; set; }
///
/// 即将断开连接(仅主动断开时有效)。
///
/// 当主动调用Close断开时,可通过终止断开行为。
///
///
public DisconnectEventHandler Disconnecting { get; set; }
///
/// 当客户端ID被修改时触发。
///
public IDChangedEventHandler IDChanged { get; set; }
///
///
///
///
///
protected override sealed void OnClientConnected(ISocketClient socketClient, TouchSocketEventArgs e)
{
OnConnected((TClient)socketClient, e);
}
///
///
///
///
///
protected override sealed void OnClientConnecting(ISocketClient socketClient, OperationEventArgs e)
{
OnConnecting((TClient)socketClient, e);
}
///
///
///
///
///
protected override sealed void OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e)
{
OnDisconnected((TClient)socketClient, e);
}
///
///
///
///
///
protected override sealed void OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e)
{
OnDisconnecting((TClient)socketClient, e);
}
///
///
///
///
///
///
protected override sealed void OnClientReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{
OnReceived((TClient)socketClient, byteBlock, requestInfo);
}
///
/// 客户端连接完成,覆盖父类方法将不会触发事件。
///
///
///
protected virtual void OnConnected(TClient socketClient, TouchSocketEventArgs e)
{
Connected?.Invoke(socketClient, e);
}
///
/// 客户端请求连接,覆盖父类方法将不会触发事件。
///
///
///
protected virtual void OnConnecting(TClient socketClient, OperationEventArgs e)
{
Connecting?.Invoke(socketClient, e);
}
///
/// 客户端断开连接,覆盖父类方法将不会触发事件。
///
///
///
protected virtual void OnDisconnected(TClient socketClient, DisconnectEventArgs e)
{
Disconnected?.Invoke(socketClient, e);
}
///
/// 即将断开连接(仅主动断开时有效)。
///
/// 当主动调用Close断开时,可通过终止断开行为。
///
///
///
///
protected virtual void OnDisconnecting(TClient socketClient, DisconnectEventArgs e)
{
Disconnecting?.Invoke(socketClient, e);
}
///
/// 当收到适配器数据。
///
///
///
///
protected virtual void OnReceived(TClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{
}
#endregion 事件
///
///
///
public override void Clear()
{
string[] ids = GetIDs();
foreach (var item in ids)
{
if (TryGetSocketClient(item, out TClient client))
{
client.Dispose();
}
}
}
///
/// 获取当前在线的所有客户端
///
///
public TClient[] GetClients()
{
var clients = m_socketClients.GetClients().ToArray();
TClient[] clients1 = new TClient[clients.Length];
for (int i = 0; i < clients.Length; i++)
{
clients1[i] = (TClient)clients[i];
}
return clients1;
}
///
///
///
///
///
///
///
public override void ResetID(string oldID, string newID)
{
if (string.IsNullOrEmpty(oldID))
{
throw new ArgumentException($"“{nameof(oldID)}”不能为 null 或空。", nameof(oldID));
}
if (string.IsNullOrEmpty(newID))
{
throw new ArgumentException($"“{nameof(newID)}”不能为 null 或空。", nameof(newID));
}
if (oldID == newID)
{
return;
}
if (m_socketClients.TryGetSocketClient(oldID, out TClient socketClient))
{
socketClient.ResetID(newID);
}
else
{
throw new ClientNotFindException(TouchSocketStatus.ClientNotFind.GetDescription(oldID));
}
}
///
///
///
///
public override IService Setup(TouchSocketConfig config)
{
m_config = config;
if (config.IsUsePlugin)
{
PluginsManager.Raise(nameof(IConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
}
LoadConfig(m_config);
if (UsePlugin)
{
PluginsManager.Raise(nameof(IConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
}
Container.RegisterTransient();
return this;
}
///
///
///
///
public override IService Setup(int port)
{
TouchSocketConfig serviceConfig = new TouchSocketConfig();
serviceConfig.SetListenIPHosts(new IPHost[] { new IPHost(port) });
return Setup(serviceConfig);
}
///
///
///
///
///
public override bool SocketClientExist(string id)
{
return SocketClients.SocketClientExist(id);
}
///
///
///
///
///
///
public override IService Start()
{
try
{
IPHost[] iPHosts = Config.GetValue(TouchSocketConfigExtension.ListenIPHostsProperty);
if (iPHosts == null || iPHosts.Length == 0)
{
throw new Exception("IPHosts为空,无法绑定");
}
switch (m_serverState)
{
case ServerState.None:
{
BeginListen(iPHosts);
break;
}
case ServerState.Running:
{
return this;
}
case ServerState.Stopped:
{
BeginListen(iPHosts);
break;
}
case ServerState.Disposed:
{
throw new Exception("无法重新利用已释放对象");
}
}
m_serverState = ServerState.Running;
if (UsePlugin)
{
PluginsManager.Raise(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, default));
}
return this;
}
catch (Exception ex)
{
m_serverState = ServerState.Exception;
if (UsePlugin)
{
PluginsManager.Raise(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, ex) { Message=ex.Message });
}
throw;
}
}
///
///
///
public override IService Stop()
{
if (m_monitors != null)
{
foreach (var item in m_monitors)
{
item.Socket?.Dispose();
}
}
m_monitors = null;
Clear();
m_serverState = ServerState.Stopped;
if (UsePlugin)
{
PluginsManager.Raise(nameof(IServicePlugin.OnStoped), this, new ServiceStateEventArgs(this.m_serverState, default));
}
return this;
}
///
/// 尝试获取TClient
///
/// ID
/// TClient
///
public bool TryGetSocketClient(string id, out TClient socketClient)
{
return m_socketClients.TryGetSocketClient(id, out socketClient);
}
///
///
///
///
protected override void Dispose(bool disposing)
{
if (!DisposedValue)
{
if (disposing)
{
if (m_monitors != null)
{
foreach (var item in m_monitors)
{
item.Socket?.Dispose();
}
m_monitors = null;
}
Clear();
m_serverState = ServerState.Disposed;
if (UsePlugin)
{
PluginsManager.Raise(nameof(IServicePlugin.OnStoped), this, new ServiceStateEventArgs(this.m_serverState, default));
}
PluginsManager.Clear();
}
}
base.Dispose(disposing);
}
///
/// 初始化客户端实例,默认实现为
///
///
protected virtual TClient GetClientInstence()
{
return Container.Resolve();
}
///
/// 加载配置
///
///
protected virtual void LoadConfig(TouchSocketConfig config)
{
if (config == null)
{
throw new Exception("配置文件为空");
}
if (config.GetValue(TouchSocketConfigExtension.GetDefaultNewIDProperty) is Func fun)
{
m_getDefaultNewID = fun;
}
m_usePlugin = config.IsUsePlugin;
m_maxCount = config.GetValue(TouchSocketConfigExtension.MaxCountProperty);
m_backlog = config.GetValue(TouchSocketConfigExtension.BacklogProperty);
BufferLength = config.GetValue(TouchSocketConfigExtension.BufferLengthProperty);
m_receiveType = config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty);
Logger ??= Container.Resolve();
if (config.GetValue(TouchSocketConfigExtension.SslOptionProperty) != null)
{
m_useSsl = true;
}
}
///
/// 在验证Ssl发送错误时。
///
///
protected virtual void OnAuthenticatingError(System.Exception ex)
{
}
///
/// 在Socket初始化对象后,Bind之前调用。
/// 可用于设置Socket参数。
/// 父类方法可覆盖。
///
///
protected virtual void PreviewBind(Socket socket)
{
}
private void Args_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.LastOperation == SocketAsyncOperation.Accept)
{
OnAccepted(e);
}
}
private void BeginListen(IPHost[] iPHosts)
{
int threadCount = Config.GetValue(TouchSocketConfigExtension.ThreadCountProperty);
if (threadCount > 0)
{
while (!ThreadPool.SetMinThreads(threadCount, threadCount))
{
if (--threadCount <= 10)
{
break;
}
}
}
List networkMonitors = new List();
foreach (var iPHost in iPHosts)
{
Socket socket = new Socket(iPHost.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
{
ReceiveBufferSize = BufferLength,
SendBufferSize = BufferLength
};
if (m_config.GetValue(TouchSocketConfigExtension.ReuseAddressProperty))
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
PreviewBind(socket);
socket.Bind(iPHost.EndPoint);
socket.Listen(m_backlog);
networkMonitors.Add(new NetworkMonitor(iPHost, socket));
}
m_monitors = networkMonitors.ToArray();
foreach (var networkMonitor in m_monitors)
{
SocketAsyncEventArgs e = new SocketAsyncEventArgs
{
UserToken = networkMonitor.Socket
};
e.Completed += Args_Completed;
if (!networkMonitor.Socket.AcceptAsync(e))
{
OnAccepted(e);
}
}
}
private void OnAccepted(SocketAsyncEventArgs e)
{
if (!DisposedValue)
{
if (e.SocketError == SocketError.Success && e.AcceptSocket != null)
{
Socket socket = e.AcceptSocket;
socket.ReceiveBufferSize = BufferLength;
socket.SendBufferSize = BufferLength;
if (SocketClients.Count < m_maxCount)
{
SocketInit(socket);
}
else
{
socket.SafeDispose();
Logger.Warning(this, "连接客户端数量已达到设定最大值");
}
}
e.AcceptSocket = null;
try
{
if (!((Socket)e.UserToken).AcceptAsync(e))
{
OnAccepted(e);
}
}
catch
{
e.Dispose();
return;
}
}
}
private void SetClientConfiguration(SocketClient client)
{
client.m_usePlugin = m_usePlugin;
client.Config = m_config;
client.m_service = this;
client.Logger = Container.Resolve();
client.m_receiveType = m_receiveType;
client.BufferLength = BufferLength;
if (client.CanSetDataHandlingAdapter)
{
client.SetDataHandlingAdapter(Config.GetValue(TouchSocketConfigExtension.DataHandlingAdapterProperty).Invoke());
}
}
private void SocketInit(Socket socket)
{
try
{
if (Config.GetValue(TouchSocketConfigExtension.NoDelayProperty))
{
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
}
TClient client = GetClientInstence();
SetClientConfiguration(client);
client.SetSocket(socket);
client.InternalInitialized();
OperationEventArgs args = new OperationEventArgs
{
ID = GetDefaultNewID()
};
client.InternalConnecting(args);//Connecting
if (args.IsPermitOperation)
{
client.m_id = args.ID;
if (SocketClients.TryAdd(client))
{
client.InternalConnected(new MsgEventArgs("客户端成功连接"));
if (!client.MainSocket.Connected)
{
return;
}
if (m_useSsl)
{
try
{
client.BeginReceiveSsl(m_receiveType, (ServiceSslOption)m_config.GetValue(TouchSocketConfigExtension.SslOptionProperty));
}
catch (System.Exception ex)
{
OnAuthenticatingError(ex);
return;
}
}
else
{
client.BeginReceive(m_receiveType);
}
}
else
{
throw new Exception($"ID={client.m_id}重复");
}
}
else
{
socket.SafeDispose();
}
}
catch (Exception ex)
{
socket.SafeDispose();
Logger.Log(LogType.Error, this, "接收新连接错误", ex);
}
}
}
///
/// TCP服务器
///
public class TcpService : TcpService
{
///
/// 处理数据
///
public ReceivedEventHandler Received { get; set; }
///
///
///
///
///
///
protected override void OnReceived(SocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{
Received?.Invoke(socketClient, byteBlock, requestInfo);
base.OnReceived(socketClient, byteBlock, requestInfo);
}
}
}