123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 |
- //------------------------------------------------------------------------------
- // 此代码版权(除特别声明或在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
- {
- /// <summary>
- /// TCP泛型服务器,由客户自己指定<see cref="SocketClient"/>类型。
- /// </summary>
- public class TcpService<TClient> : TcpServiceBase, ITcpService<TClient> where TClient : SocketClient
- {
- /// <summary>
- /// 构造函数
- /// </summary>
- 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<string> 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 属性
- /// <summary>
- /// 获取服务器配置
- /// </summary>
- public override TouchSocketConfig Config => m_config;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override IContainer Container => Config?.Container;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override Func<string> GetDefaultNewID => m_getDefaultNewID;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override int MaxCount => m_maxCount;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override NetworkMonitor[] Monitors => m_monitors;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override IPluginsManager PluginsManager => Config?.PluginsManager;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override string ServerName => Config?.GetValue<string>(TouchSocketConfigExtension.ServerNameProperty);
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override ServerState ServerState => m_serverState;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override SocketClientCollection SocketClients => m_socketClients;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override bool UsePlugin => m_usePlugin;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override bool UseSsl => m_useSsl;
- #endregion 属性
- #region 事件
- /// <summary>
- /// 用户连接完成
- /// </summary>
- public TouchSocketEventHandler<TClient> Connected { get; set; }
- /// <summary>
- /// 有用户连接的时候
- /// </summary>
- public OperationEventHandler<TClient> Connecting { get; set; }
- /// <summary>
- /// 有用户断开连接
- /// </summary>
- public DisconnectEventHandler<TClient> Disconnected { get; set; }
- /// <summary>
- /// 即将断开连接(仅主动断开时有效)。
- /// <para>
- /// 当主动调用Close断开时,可通过<see cref="TouchSocketEventArgs.IsPermitOperation"/>终止断开行为。
- /// </para>
- /// </summary>
- public DisconnectEventHandler<TClient> Disconnecting { get; set; }
- /// <summary>
- /// 当客户端ID被修改时触发。
- /// </summary>
- public IDChangedEventHandler<TClient> IDChanged { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected override sealed void OnClientConnected(ISocketClient socketClient, TouchSocketEventArgs e)
- {
- OnConnected((TClient)socketClient, e);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected override sealed void OnClientConnecting(ISocketClient socketClient, OperationEventArgs e)
- {
- OnConnecting((TClient)socketClient, e);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected override sealed void OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e)
- {
- OnDisconnected((TClient)socketClient, e);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected override sealed void OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e)
- {
- OnDisconnecting((TClient)socketClient, e);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="byteBlock"></param>
- /// <param name="requestInfo"></param>
- protected override sealed void OnClientReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- OnReceived((TClient)socketClient, byteBlock, requestInfo);
- }
- /// <summary>
- /// 客户端连接完成,覆盖父类方法将不会触发事件。
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected virtual void OnConnected(TClient socketClient, TouchSocketEventArgs e)
- {
- Connected?.Invoke(socketClient, e);
- }
- /// <summary>
- /// 客户端请求连接,覆盖父类方法将不会触发事件。
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected virtual void OnConnecting(TClient socketClient, OperationEventArgs e)
- {
- Connecting?.Invoke(socketClient, e);
- }
- /// <summary>
- /// 客户端断开连接,覆盖父类方法将不会触发事件。
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected virtual void OnDisconnected(TClient socketClient, DisconnectEventArgs e)
- {
- Disconnected?.Invoke(socketClient, e);
- }
- /// <summary>
- /// 即将断开连接(仅主动断开时有效)。
- /// <para>
- /// 当主动调用Close断开时,可通过<see cref="TouchSocketEventArgs.IsPermitOperation"/>终止断开行为。
- /// </para>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="e"></param>
- protected virtual void OnDisconnecting(TClient socketClient, DisconnectEventArgs e)
- {
- Disconnecting?.Invoke(socketClient, e);
- }
- /// <summary>
- /// 当收到适配器数据。
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="byteBlock"></param>
- /// <param name="requestInfo"></param>
- protected virtual void OnReceived(TClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- }
- #endregion 事件
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public override void Clear()
- {
- string[] ids = GetIDs();
- foreach (var item in ids)
- {
- if (TryGetSocketClient(item, out TClient client))
- {
- client.Dispose();
- }
- }
- }
- /// <summary>
- /// 获取当前在线的所有客户端
- /// </summary>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="oldID"></param>
- /// <param name="newID"></param>
- /// <exception cref="ClientNotFindException"></exception>
- /// <exception cref="Exception"></exception>
- 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));
- }
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="config"></param>
- public override IService Setup(TouchSocketConfig config)
- {
- m_config = config;
- if (config.IsUsePlugin)
- {
- PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
- }
- LoadConfig(m_config);
- if (UsePlugin)
- {
- PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
- }
- Container.RegisterTransient<TClient>();
- return this;
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="port"></param>
- public override IService Setup(int port)
- {
- TouchSocketConfig serviceConfig = new TouchSocketConfig();
- serviceConfig.SetListenIPHosts(new IPHost[] { new IPHost(port) });
- return Setup(serviceConfig);
- }
- /// <summary>
- ///<inheritdoc/>
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- public override bool SocketClientExist(string id)
- {
- return SocketClients.SocketClientExist(id);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <exception cref="Exception"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- /// <exception cref="System.Exception"></exception>
- 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<IServicePlugin>(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, default));
- }
- return this;
- }
- catch (Exception ex)
- {
- m_serverState = ServerState.Exception;
- if (UsePlugin)
- {
- PluginsManager.Raise<IServicePlugin>(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, ex) { Message=ex.Message });
- }
- throw;
- }
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- 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<IServicePlugin>(nameof(IServicePlugin.OnStoped), this, new ServiceStateEventArgs(this.m_serverState, default));
- }
- return this;
- }
- /// <summary>
- /// 尝试获取TClient
- /// </summary>
- /// <param name="id">ID</param>
- /// <param name="socketClient">TClient</param>
- /// <returns></returns>
- public bool TryGetSocketClient(string id, out TClient socketClient)
- {
- return m_socketClients.TryGetSocketClient(id, out socketClient);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="disposing"></param>
- 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<IServicePlugin>(nameof(IServicePlugin.OnStoped), this, new ServiceStateEventArgs(this.m_serverState, default));
- }
- PluginsManager.Clear();
- }
- }
- base.Dispose(disposing);
- }
- /// <summary>
- /// 初始化客户端实例,默认实现为<see cref="Container.Resolve(Type, object[], string)"/>
- /// </summary>
- /// <returns></returns>
- protected virtual TClient GetClientInstence()
- {
- return Container.Resolve<TClient>();
- }
- /// <summary>
- /// 加载配置
- /// </summary>
- /// <param name="config"></param>
- protected virtual void LoadConfig(TouchSocketConfig config)
- {
- if (config == null)
- {
- throw new Exception("配置文件为空");
- }
- if (config.GetValue(TouchSocketConfigExtension.GetDefaultNewIDProperty) is Func<string> 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<ILog>();
- if (config.GetValue(TouchSocketConfigExtension.SslOptionProperty) != null)
- {
- m_useSsl = true;
- }
- }
- /// <summary>
- /// 在验证Ssl发送错误时。
- /// </summary>
- /// <param name="ex"></param>
- protected virtual void OnAuthenticatingError(System.Exception ex)
- {
- }
- /// <summary>
- /// 在Socket初始化对象后,Bind之前调用。
- /// 可用于设置Socket参数。
- /// 父类方法可覆盖。
- /// </summary>
- /// <param name="socket"></param>
- 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<NetworkMonitor> networkMonitors = new List<NetworkMonitor>();
- 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<ILog>();
- 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);
- }
- }
- }
- /// <summary>
- /// TCP服务器
- /// </summary>
- public class TcpService : TcpService<SocketClient>
- {
- /// <summary>
- /// 处理数据
- /// </summary>
- public ReceivedEventHandler<SocketClient> Received { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="socketClient"></param>
- /// <param name="byteBlock"></param>
- /// <param name="requestInfo"></param>
- protected override void OnReceived(SocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- Received?.Invoke(socketClient, byteBlock, requestInfo);
- base.OnReceived(socketClient, byteBlock, requestInfo);
- }
- }
- }
|