123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964 |
- //------------------------------------------------------------------------------
- // 此代码版权(除特别声明或在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.Diagnostics;
- using System.IO;
- using System.Net.Security;
- using System.Net.Sockets;
- using System.Threading.Tasks;
- using TouchSocket.Core;
- using TouchSocket.Resources;
- namespace TouchSocket.Sockets
- {
- /// <summary>
- /// 服务器辅助类
- /// </summary>
- [DebuggerDisplay("ID={ID},IPAdress={IP}:{Port}")]
- public class SocketClient : BaseSocket, ISocketClient
- {
- /// <summary>
- /// 构造函数
- /// </summary>
- public SocketClient()
- {
- Protocol = Protocol.TCP;
- }
- #region 变量
- internal string m_id;
- internal ReceiveType m_receiveType;
- internal TcpServiceBase m_service;
- internal bool m_usePlugin;
- private DataHandlingAdapter m_adapter;
- private DelaySender m_delaySender;
- private Socket m_mainSocket;
- //private int m_maxPackageSize;
- private bool m_online;
- private bool m_useDelaySender;
- private Stream m_workStream;
- #endregion 变量
- #region 属性
- /// <inheritdoc/>
- public bool IsClient => false;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool CanSend => m_online;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public virtual bool CanSetDataHandlingAdapter => true;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public TouchSocketConfig Config { get; internal set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public IContainer Container => Config?.Container;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DataHandlingAdapter DataHandlingAdapter => m_adapter;
- /// <summary>
- /// 用于索引的ID
- /// </summary>
- public string ID => m_id;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public string IP { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public Socket MainSocket => m_mainSocket;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool Online => m_online;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public IPluginsManager PluginsManager => Config?.PluginsManager;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public int Port { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public Protocol Protocol { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public ReceiveType ReceiveType => m_receiveType;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public TcpServiceBase Service => m_service;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool UsePlugin => m_usePlugin;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool UseSsl { get; private set; }
- #endregion 属性
- #region 事件&委托
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DisconnectEventHandler<ITcpClientBase> Disconnected { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DisconnectEventHandler<ITcpClientBase> Disconnecting { get; set; }
- /// <summary>
- /// 即将断开连接(仅主动断开时有效)。
- /// <para>
- /// 当主动调用Close断开时,可通过<see cref="TouchSocketEventArgs.IsPermitOperation"/>终止断开行为。
- /// </para>
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnDisconnecting(DisconnectEventArgs e)
- {
- try
- {
- Disconnecting?.Invoke(this, e);
- }
- catch (Exception ex)
- {
- Logger.Log(LogType.Error, this, $"在事件{nameof(Disconnecting)}中发生错误。", ex);
- }
- }
- /// <summary>
- /// 当客户端完整建立TCP连接,如果覆盖父类方法,则不会触发插件。
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnConnected(TouchSocketEventArgs e)
- {
- m_service.OnInternalConnected(this, e);
- }
- /// <summary>
- /// 客户端正在连接,如果覆盖父类方法,则不会触发插件。
- /// </summary>
- protected virtual void OnConnecting(OperationEventArgs e)
- {
- m_service.OnInternalConnecting(this, e);
- }
- /// <summary>
- /// 在延迟发生错误
- /// </summary>
- /// <param name="ex"></param>
- protected virtual void OnDelaySenderError(Exception ex)
- {
- Logger.Log(LogType.Error, this, "发送错误", ex);
- }
- /// <summary>
- /// 客户端已断开连接,如果从Connecting中拒绝连接,则不会触发。如果覆盖父类方法,则不会触发插件。
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnDisconnected(DisconnectEventArgs e)
- {
- Disconnected?.Invoke(this, e);
- }
- /// <summary>
- /// 当初始化完成时,执行在<see cref="OnConnecting(OperationEventArgs)"/>之前。
- /// </summary>
- protected virtual void OnInitialized()
- {
- }
- private void PrivateOnDisconnected(DisconnectEventArgs e)
- {
- if (m_usePlugin && PluginsManager.Raise<IDisconnectedPlguin>(nameof(IDisconnectedPlguin.OnDisconnected), this, e))
- {
- return;
- }
- OnDisconnected(e);
- if (!e.Handled)
- {
- m_service.OnInternalDisconnected(this, e);
- }
- }
- private void PrivateOnDisconnecting(DisconnectEventArgs e)
- {
- if (m_usePlugin && PluginsManager.Raise<IDisconnectingPlugin>(nameof(IDisconnectingPlugin.OnDisconnecting), this, e))
- {
- return;
- }
- OnDisconnecting(e);
- if (!e.Handled)
- {
- m_service.OnInternalDisconnecting(this, e);
- }
- }
- #endregion 事件&委托
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DateTime LastReceivedTime { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DateTime LastSendTime { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
- /// <summary>
- ///<inheritdoc/>
- /// </summary>
- public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public string ServiceIP { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public int ServicePort { get; private set; }
- /// <inheritdoc/>
- public virtual void Close()
- {
- Close($"主动调用{nameof(Close)}");
- }
- /// <inheritdoc/>
- public virtual void Close(string msg)
- {
- if (this.m_online)
- {
- var args = new DisconnectEventArgs(true, msg)
- {
- IsPermitOperation = true
- };
- PrivateOnDisconnecting(args);
- if (this.DisposedValue || args.IsPermitOperation)
- {
- BreakOut(msg, true);
- }
- }
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <returns></returns>
- public Stream GetStream()
- {
- if (m_workStream == null)
- {
- m_workStream = new NetworkStream(m_mainSocket, true);
- }
- return m_workStream;
- }
- /// <summary>
- /// 直接重置内部ID。
- /// </summary>
- /// <param name="newId"></param>
- protected void DirectResetID(string newId)
- {
- if (string.IsNullOrEmpty(newId))
- {
- throw new ArgumentException($"“{nameof(newId)}”不能为 null 或空。", nameof(newId));
- }
- if (m_id == newId)
- {
- return;
- }
- string oldId = m_id;
- if (Service.SocketClients.TryRemove(m_id, out SocketClient socketClient))
- {
- socketClient.m_id = newId;
- if (Service.SocketClients.TryAdd(socketClient))
- {
- if (m_usePlugin)
- {
- IDChangedEventArgs e = new IDChangedEventArgs(oldId, newId);
- PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnIDChanged), socketClient, e);
- }
- return;
- }
- else
- {
- socketClient.m_id = oldId;
- if (Service.SocketClients.TryAdd(socketClient))
- {
- throw new Exception("ID重复");
- }
- else
- {
- socketClient.Close("修改新ID时操作失败,且回退旧ID时也失败。");
- }
- }
- }
- else
- {
- throw new ClientNotFindException(TouchSocketStatus.ClientNotFind.GetDescription(oldId));
- }
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="newId"></param>
- /// <exception cref="ArgumentException"></exception>
- /// <exception cref="ClientNotFindException"></exception>
- /// <exception cref="Exception"></exception>
- public virtual void ResetID(string newId)
- {
- DirectResetID(newId);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="adapter"></param>
- public virtual void SetDataHandlingAdapter(DataHandlingAdapter adapter)
- {
- if (!CanSetDataHandlingAdapter)
- {
- throw new Exception($"不允许自由调用{nameof(SetDataHandlingAdapter)}进行赋值。");
- }
- SetAdapter(adapter);
- }
- internal void BeginReceive(ReceiveType receiveType)
- {
- try
- {
- if (receiveType == ReceiveType.Auto)
- {
- SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
- eventArgs.Completed += EventArgs_Completed;
- ByteBlock byteBlock = BytePool.Default.GetByteBlock(BufferLength);
- eventArgs.UserToken = byteBlock;
- eventArgs.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
- if (!m_mainSocket.ReceiveAsync(eventArgs))
- {
- ProcessReceived(eventArgs);
- }
- }
- }
- catch (Exception ex)
- {
- BreakOut(ex.Message, false);
- }
- }
- internal void BeginReceiveSsl(ReceiveType receiveType, ServiceSslOption sslOption)
- {
- SslStream sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(m_mainSocket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(m_mainSocket, false), false);
- sslStream.AuthenticateAsServer(sslOption.Certificate, sslOption.ClientCertificateRequired, sslOption.SslProtocols, sslOption.CheckCertificateRevocation);
- m_workStream = sslStream;
- UseSsl = true;
- if (receiveType == ReceiveType.Auto)
- {
- BeginSsl();
- }
- }
- internal void InternalConnected(TouchSocketEventArgs e)
- {
- m_online = true;
- if (Config.GetValue<DelaySenderOption>(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption)
- {
- m_useDelaySender = true;
- m_delaySender.SafeDispose();
- m_delaySender = new DelaySender(m_mainSocket, senderOption.QueueLength, OnDelaySenderError)
- {
- DelayLength = senderOption.DelayLength
- };
- }
- if (m_usePlugin && PluginsManager.Raise<IConnectedPlugin>(nameof(IConnectedPlugin.OnConnected), this, e))
- {
- return;
- }
- OnConnected(e);
- }
- internal void InternalConnecting(OperationEventArgs e)
- {
- if (m_usePlugin && PluginsManager.Raise<IConnectingPlugin>(nameof(IConnectingPlugin.OnConnecting), this, e))
- {
- return;
- }
- OnConnecting(e);
- }
- internal void InternalInitialized()
- {
- LastReceivedTime = DateTime.Now;
- LastSendTime = DateTime.Now;
- OnInitialized();
- }
- internal void SetSocket(Socket mainSocket)
- {
- m_mainSocket = mainSocket ?? throw new ArgumentNullException(nameof(mainSocket));
- IP = mainSocket.RemoteEndPoint.GetIP();
- Port = mainSocket.RemoteEndPoint.GetPort();
- ServiceIP = mainSocket.LocalEndPoint.GetIP();
- ServicePort = mainSocket.LocalEndPoint.GetPort();
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="disposing"></param>
- protected override void Dispose(bool disposing)
- {
- if (this.m_online)
- {
- var args = new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开");
- PrivateOnDisconnecting(args);
- }
- m_adapter.SafeDispose();
- m_adapter = default;
- BreakOut($"{nameof(Dispose)}主动断开", true);
- base.Dispose(disposing);
- }
- /// <summary>
- /// 处理已接收到的数据。
- /// <para>根据不同的数据处理适配器,会传递不同的数据</para>
- /// </summary>
- /// <param name="byteBlock">以二进制流形式传递</param>
- /// <param name="requestInfo">以解析的数据对象传递</param>
- protected virtual void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- }
- /// <summary>
- /// 当即将发送时,如果覆盖父类方法,则不会触发插件。
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="offset">偏移</param>
- /// <param name="length">长度</param>
- /// <returns>返回值表示是否允许发送</returns>
- protected virtual bool HandleSendingData(byte[] buffer, int offset, int length)
- {
- if (m_usePlugin)
- {
- SendingEventArgs args = new SendingEventArgs(buffer, offset, length);
- PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnSendingData), this, args);
- if (args.IsPermitOperation)
- {
- return true;
- }
- return false;
- }
- return true;
- }
-
- /// <summary>
- /// 设置适配器,该方法不会检验<see cref="CanSetDataHandlingAdapter"/>的值。
- /// </summary>
- /// <param name="adapter"></param>
- protected void SetAdapter(DataHandlingAdapter adapter)
- {
- if (adapter is null)
- {
- throw new ArgumentNullException(nameof(adapter));
- }
- if (Config != null)
- {
- if (Config.GetValue(TouchSocketConfigExtension.MaxPackageSizeProperty) is int v1)
- {
- adapter.MaxPackageSize = v1;
- }
- if (Config.GetValue(TouchSocketConfigExtension.CacheTimeoutProperty) != TimeSpan.Zero)
- {
- adapter.CacheTimeout = Config.GetValue(TouchSocketConfigExtension.CacheTimeoutProperty);
- }
- if (Config.GetValue(TouchSocketConfigExtension.CacheTimeoutEnableProperty) is bool v2)
- {
- adapter.CacheTimeoutEnable = v2;
- }
- if (Config.GetValue(TouchSocketConfigExtension.UpdateCacheTimeWhenRevProperty) is bool v3)
- {
- adapter.UpdateCacheTimeWhenRev = v3;
- }
- }
- adapter.OnLoaded(this);
- adapter.ReceivedCallBack = PrivateHandleReceivedData;
- adapter.SendCallBack = DefaultSend;
- m_adapter = adapter;
- }
- private void BeginSsl()
- {
- if (!DisposedValue)
- {
- ByteBlock byteBlock = new ByteBlock(BufferLength);
- try
- {
- m_workStream.BeginRead(byteBlock.Buffer, 0, byteBlock.Capacity, EndSsl, byteBlock);
- }
- catch (System.Exception ex)
- {
- byteBlock.Dispose();
- BreakOut(ex.Message, false);
- }
- }
- }
- private void BreakOut(string msg, bool manual)
- {
- lock (this.SyncRoot)
- {
- if (m_online)
- {
- m_online = false;
- this.TryShutdown();
- m_mainSocket.SafeDispose();
- m_delaySender.SafeDispose();
- m_adapter.SafeDispose();
- m_service?.SocketClients.TryRemove(m_id, out _);
- PrivateOnDisconnected(new DisconnectEventArgs(manual, msg));
- Disconnected = null;
- }
- base.Dispose(true);
- }
- }
- private void EndSsl(IAsyncResult result)
- {
- ByteBlock byteBlock = (ByteBlock)result.AsyncState;
- try
- {
- int r = m_workStream.EndRead(result);
- if (r == 0)
- {
- BreakOut("远程终端主动关闭", false);
- }
- byteBlock.SetLength(r);
- HandleBuffer(byteBlock);
- BeginSsl();
- }
- catch (Exception ex)
- {
- byteBlock.Dispose();
- BreakOut(ex.Message, false);
- }
- }
- private void EventArgs_Completed(object sender, SocketAsyncEventArgs e)
- {
- try
- {
- ProcessReceived(e);
- }
- catch (Exception ex)
- {
- e.SafeDispose();
- BreakOut(ex.Message, false);
- }
- }
- private void HandleBuffer(ByteBlock byteBlock)
- {
- try
- {
- LastReceivedTime = DateTime.Now;
- if (OnHandleRawBuffer?.Invoke(byteBlock) == false)
- {
- return;
- }
- if (UsePlugin && PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnReceivingData), this, new ByteBlockEventArgs(byteBlock)))
- {
- return;
- }
- if (DisposedValue)
- {
- return;
- }
- if (m_adapter == null)
- {
- Logger.Error(this, TouchSocketStatus.NullDataAdapter.GetDescription());
- return;
- }
- m_adapter.ReceivedInput(byteBlock);
- }
- catch (System.Exception ex)
- {
- Logger.Log(LogType.Error, this, "在处理数据时发生错误", ex);
- }
- finally
- {
- byteBlock.Dispose();
- }
- }
- private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- if (OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
- {
- return;
- }
- if (m_usePlugin)
- {
- ReceivedDataEventArgs args = new ReceivedDataEventArgs(byteBlock, requestInfo);
- PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnReceivedData), this, args);
- if (args.Handled)
- {
- return;
- }
- }
- HandleReceivedData(byteBlock, requestInfo);
- m_service.OnInternalReceivedData(this, byteBlock, requestInfo);
- }
-
- private void ProcessReceived(SocketAsyncEventArgs e)
- {
- if (DisposedValue)
- {
- e.SafeDispose();
- }
- else
- {
- if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
- {
- ByteBlock byteBlock = (ByteBlock)e.UserToken;
- byteBlock.SetLength(e.BytesTransferred);
- HandleBuffer(byteBlock);
- try
- {
- ByteBlock newByteBlock = new ByteBlock(BufferLength);
- e.UserToken = newByteBlock;
- e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Capacity);
- if (!m_mainSocket.ReceiveAsync(e))
- {
- ProcessReceived(e);
- }
- }
- catch (Exception ex)
- {
- BreakOut(ex.Message, false);
- }
- }
- else
- {
- e.SafeDispose();
- BreakOut("远程主机主动断开连接", false);
- }
- }
- }
- #region 发送
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="offset"></param>
- /// <param name="length"></param>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public void DefaultSend(byte[] buffer, int offset, int length)
- {
- if (!m_online)
- {
- throw new NotConnectedException(TouchSocketStatus.NotConnected.GetDescription());
- }
- if (HandleSendingData(buffer, offset, length))
- {
- if (UseSsl)
- {
- m_workStream.Write(buffer, offset, length);
- }
- else
- {
- if (m_useDelaySender && length < TouchSocketUtility.BigDataBoundary)
- {
- m_delaySender.Send(new QueueDataBytes(buffer, offset, length));
- }
- else
- {
- m_mainSocket.AbsoluteSend(buffer, offset, length);
- }
- }
- LastSendTime = DateTime.Now;
- }
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="buffer"><inheritdoc/></param>
- /// <param name="offset"><inheritdoc/></param>
- /// <param name="length"><inheritdoc/></param>
- /// <exception cref="NotConnectedException"><inheritdoc/></exception>
- /// <exception cref="OverlengthException"><inheritdoc/></exception>
- /// <exception cref="Exception"><inheritdoc/></exception>
- public Task DefaultSendAsync(byte[] buffer, int offset, int length)
- {
- return EasyTask.Run(() =>
- {
- DefaultSend(buffer, offset, length);
- });
- }
- #region 同步发送
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="requestInfo"></param>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public virtual void Send(IRequestInfo requestInfo)
- {
- if (DisposedValue)
- {
- return;
- }
- if (m_adapter == null)
- {
- throw new ArgumentNullException(nameof(DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
- }
- if (!m_adapter.CanSendRequestInfo)
- {
- throw new NotSupportedException($"当前适配器不支持对象发送。");
- }
- m_adapter.SendInput(requestInfo);
- }
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="offset"></param>
- /// <param name="length"></param>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public virtual void Send(byte[] buffer, int offset, int length)
- {
- if (DisposedValue)
- {
- return;
- }
- if (m_adapter == null)
- {
- throw new ArgumentNullException(nameof(DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
- }
- m_adapter.SendInput(buffer, offset, length);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="transferBytes"></param>
- public virtual void Send(IList<ArraySegment<byte>> transferBytes)
- {
- if (DisposedValue)
- {
- return;
- }
- if (m_adapter == null)
- {
- throw new ArgumentNullException(nameof(DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
- }
- if (m_adapter.CanSplicingSend)
- {
- m_adapter.SendInput(transferBytes);
- }
- else
- {
- ByteBlock byteBlock = new ByteBlock(BufferLength);
- try
- {
- foreach (var item in transferBytes)
- {
- byteBlock.Write(item.Array, item.Offset, item.Count);
- }
- m_adapter.SendInput(byteBlock.Buffer, 0, byteBlock.Len);
- }
- finally
- {
- byteBlock.Dispose();
- }
- }
- }
- #endregion 同步发送
- #region 异步发送
- /// <summary>
- /// IOCP发送
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="offset"></param>
- /// <param name="length"></param>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public virtual Task SendAsync(byte[] buffer, int offset, int length)
- {
- return EasyTask.Run(() =>
- {
- Send(buffer, offset, length);
- });
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="requestInfo"></param>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public virtual Task SendAsync(IRequestInfo requestInfo)
- {
- return EasyTask.Run(() =>
- {
- Send(requestInfo);
- });
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="transferBytes"></param>
- public virtual Task SendAsync(IList<ArraySegment<byte>> transferBytes)
- {
- return EasyTask.Run(() =>
- {
- Send(transferBytes);
- });
- }
- #endregion 异步发送
- #region ID发送
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="id">用于检索TcpSocketClient</param>
- /// <param name="buffer"></param>
- /// <param name="offset"></param>
- /// <param name="length"></param>
- /// <exception cref="KeyNotFoundException"></exception>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public void Send(string id, byte[] buffer, int offset, int length)
- {
- m_service.Send(id, buffer, offset, length);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="id"></param>
- /// <param name="requestInfo"></param>
- public void Send(string id, IRequestInfo requestInfo)
- {
- m_service.Send(id, requestInfo);
- }
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="id">用于检索TcpSocketClient</param>
- /// <param name="buffer"></param>
- /// <param name="offset"></param>
- /// <param name="length"></param>
- /// <exception cref="KeyNotFoundException"></exception>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public Task SendAsync(string id, byte[] buffer, int offset, int length)
- {
- return m_service.SendAsync(id, buffer, offset, length);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="id"></param>
- /// <param name="requestInfo"></param>
- public Task SendAsync(string id, IRequestInfo requestInfo)
- {
- return m_service.SendAsync(id, requestInfo);
- }
- #endregion ID发送
- #endregion 发送
- }
- }
|