123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086 |
- //------------------------------------------------------------------------------
- // 此代码版权(除特别声明或在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.IO;
- using System.Net.Security;
- using System.Net.Sockets;
- using System.Runtime.InteropServices;
- using System.Threading.Tasks;
- using TouchSocket.Core;
- using TouchSocket.Resources;
- namespace TouchSocket.Sockets
- {
- /// <summary>
- /// 简单TCP客户端
- /// </summary>
- public class TcpClient : TcpClientBase
- {
- /// <summary>
- /// 接收到数据
- /// </summary>
- public ReceivedEventHandler<TcpClient> Received { get; set; }
- /// <summary>
- /// 接收数据
- /// </summary>
- /// <param name="byteBlock"></param>
- /// <param name="requestInfo"></param>
- protected override void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- this.Received?.Invoke(this, byteBlock, requestInfo);
- base.HandleReceivedData(byteBlock, requestInfo);
- }
- }
- /// <summary>
- /// TCP客户端
- /// </summary>
- [System.Diagnostics.DebuggerDisplay("{IP}:{Port}")]
- public class TcpClientBase : BaseSocket, ITcpClient
- {
- /// <summary>
- /// 构造函数
- /// </summary>
- public TcpClientBase()
- {
- this.Protocol = Protocol.TCP;
- }
- #region 变量
- private DelaySender m_delaySender;
- private bool m_useDelaySender;
- private Stream m_workStream;
- #endregion 变量
- #region 事件
- /// <summary>
- /// 成功连接到服务器
- /// </summary>
- public MessageEventHandler<ITcpClient> Connected { get; set; }
- /// <summary>
- /// 准备连接的时候,此时已初始化Socket,但是并未建立Tcp连接
- /// </summary>
- public ConnectingEventHandler<ITcpClient> Connecting { get; set; }
- /// <summary>
- /// 断开连接。在客户端未设置连接状态时,不会触发
- /// </summary>
- public DisconnectEventHandler<ITcpClientBase> Disconnected { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DisconnectEventHandler<ITcpClientBase> Disconnecting { get; set; }
- private void PrivateOnConnected(MsgEventArgs e)
- {
- if (this.UsePlugin)
- {
- this.PluginsManager.Raise<IConnectedPlugin>(nameof(IConnectedPlugin.OnConnected), this, e);
- if (e.Handled)
- {
- return;
- }
- }
- this.OnConnected(e);
- }
- /// <summary>
- /// 已经建立Tcp连接
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnConnected(MsgEventArgs e)
- {
- try
- {
- this.Connected?.Invoke(this, e);
- }
- catch (System.Exception ex)
- {
- this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.Connected)}中发生错误。", ex);
- }
- }
- private void PrivateOnConnecting(ConnectingEventArgs e)
- {
- this.LastReceivedTime = DateTime.Now;
- this.LastSendTime = DateTime.Now;
- if (this.CanSetDataHandlingAdapter)
- {
- this.SetDataHandlingAdapter(this.Config.GetValue<Func<DataHandlingAdapter>>(TouchSocketConfigExtension.DataHandlingAdapterProperty).Invoke());
- }
- if (this.UsePlugin)
- {
- this.PluginsManager.Raise<IConnectingPlugin>(nameof(IConnectingPlugin.OnConnecting), this, e);
- if (e.Handled)
- {
- return;
- }
- }
- this.OnConnecting(e);
- }
- /// <summary>
- /// 准备连接的时候,此时已初始化Socket,但是并未建立Tcp连接
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnConnecting(ConnectingEventArgs e)
- {
- try
- {
- this.Connecting?.Invoke(this, e);
- }
- catch (Exception ex)
- {
- this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.OnConnecting)}中发生错误。", ex);
- }
- }
- private void PrivateOnDisconnected(DisconnectEventArgs e)
- {
- if (this.UsePlugin && this.PluginsManager.Raise<IDisconnectedPlguin>(nameof(IDisconnectedPlguin.OnDisconnected), this, e))
- {
- return;
- }
- this.OnDisconnected(e);
- }
- /// <summary>
- /// 断开连接。在客户端未设置连接状态时,不会触发
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnDisconnected(DisconnectEventArgs e)
- {
- try
- {
- this.Disconnected?.Invoke(this, e);
- }
- catch (Exception ex)
- {
- this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.Disconnected)}中发生错误。", ex);
- }
- }
- private void PrivateOnDisconnecting(DisconnectEventArgs e)
- {
- if (this.UsePlugin && this.PluginsManager.Raise<IDisconnectingPlugin>(nameof(IDisconnectingPlugin.OnDisconnecting), this, e))
- {
- return;
- }
- this.OnDisconnecting(e);
- }
- /// <summary>
- /// 即将断开连接(仅主动断开时有效)。
- /// <para>
- /// 当主动调用Close断开时,可通过<see cref="TouchSocketEventArgs.IsPermitOperation"/>终止断开行为。
- /// </para>
- /// </summary>
- /// <param name="e"></param>
- protected virtual void OnDisconnecting(DisconnectEventArgs e)
- {
- try
- {
- this.Disconnecting?.Invoke(this, e);
- }
- catch (Exception ex)
- {
- this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.Disconnecting)}中发生错误。", ex);
- }
- }
- #endregion 事件
- #region 属性
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DateTime LastReceivedTime { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public DateTime LastSendTime { get; private set; }
- /// <summary>
- /// 处理未经过适配器的数据。返回值表示是否继续向下传递。
- /// </summary>
- public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
- /// <summary>
- /// 处理经过适配器后的数据。返回值表示是否继续向下传递。
- /// </summary>
- public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public IContainer Container => this.Config?.Container;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public virtual bool CanSetDataHandlingAdapter => true;
- /// <summary>
- /// 客户端配置
- /// </summary>
- public TouchSocketConfig Config { get; private set; }
- /// <summary>
- /// 数据处理适配器
- /// </summary>
- public DataHandlingAdapter DataHandlingAdapter { get; private set; }
- /// <summary>
- /// IP地址
- /// </summary>
- public string IP { get; private set; }
- /// <summary>
- /// 主通信器
- /// </summary>
- public Socket MainSocket { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool CanSend { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool Online => this.CanSend;
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public IPluginsManager PluginsManager { get; private set; }
- /// <summary>
- /// 端口号
- /// </summary>
- public int Port { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public ReceiveType ReceiveType { get; private set; }
- /// <summary>
- /// 是否已启用插件
- /// </summary>
- public bool UsePlugin { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public bool UseSsl { get; private set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public Protocol Protocol { get; set; }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public IPHost RemoteIPHost { get; private set; }
- /// <inheritdoc/>
- public bool IsClient => true;
- #endregion 属性
- #region 断开操作
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- public virtual void Close()
- {
- this.Close($"{nameof(Close)}主动断开");
- }
- /// <summary>
- /// 中断终端,传递中断消息。
- /// </summary>
- /// <param name="msg"></param>
- public virtual void Close(string msg)
- {
- if (this.CanSend)
- {
- var args = new DisconnectEventArgs(true, msg)
- {
- IsPermitOperation = true
- };
- this.PrivateOnDisconnecting(args);
- if (this.DisposedValue || args.IsPermitOperation)
- {
- this.BreakOut(msg, true);
- }
- }
- }
- private void BreakOut(string msg, bool manual)
- {
- lock (this.SyncRoot)
- {
- if (this.CanSend)
- {
- this.CanSend = false;
- this.TryShutdown();
- this.MainSocket.SafeDispose();
- this.m_delaySender.SafeDispose();
- this.m_workStream.SafeDispose();
- this.DataHandlingAdapter.SafeDispose();
- this.PrivateOnDisconnected(new DisconnectEventArgs(manual, msg));
- }
- }
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="disposing"></param>
- protected override void Dispose(bool disposing)
- {
- if (this.CanSend)
- {
- var args = new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开");
- this.PrivateOnDisconnecting(args);
- }
- this.PluginsManager?.Clear();
- this.Config = default;
- this.DataHandlingAdapter.SafeDispose();
- this.DataHandlingAdapter = default;
- this.BreakOut($"{nameof(Dispose)}主动断开", true);
- base.Dispose(disposing);
- }
- #endregion 断开操作
- /// <summary>
- /// 建立Tcp的连接。
- /// </summary>
- /// <param name="timeout"></param>
- /// <exception cref="ObjectDisposedException"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- /// <exception cref="Exception"></exception>
- /// <exception cref="TimeoutException"></exception>
- protected void TcpConnect(int timeout)
- {
- lock (this.SyncRoot)
- {
- if (this.CanSend)
- {
- return;
- }
- if (this.DisposedValue)
- {
- throw new ObjectDisposedException(this.GetType().FullName);
- }
- if (this.Config == null)
- {
- throw new ArgumentNullException("配置文件不能为空。");
- }
- IPHost iPHost = this.Config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
- if (iPHost == null)
- {
- throw new ArgumentNullException("iPHost不能为空。");
- }
- if (this.MainSocket != null)
- {
- this.MainSocket.Dispose();
- }
- this.MainSocket = this.CreateSocket(iPHost);
- ConnectingEventArgs args = new ConnectingEventArgs(this.MainSocket);
- this.PrivateOnConnecting(args);
- if (timeout == 5000)
- {
- this.MainSocket.Connect(iPHost.EndPoint);
- this.CanSend = true;
- this.LoadSocketAndReadIpPort();
- if (this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption)
- {
- this.m_useDelaySender = true;
- this.m_delaySender.SafeDispose();
- this.m_delaySender = new DelaySender(this.MainSocket, senderOption.QueueLength, this.OnDelaySenderError)
- {
- DelayLength = senderOption.DelayLength
- };
- }
- this.BeginReceive();
- this.PrivateOnConnected(new MsgEventArgs("连接成功"));
- }
- else
- {
- var result = this.MainSocket.BeginConnect(iPHost.EndPoint, null, null);
- if (result.AsyncWaitHandle.WaitOne(timeout))
- {
- if (this.MainSocket.Connected)
- {
- this.MainSocket.EndConnect(result);
- this.CanSend = true;
- this.LoadSocketAndReadIpPort();
- if (this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption)
- {
- this.m_useDelaySender = true;
- this.m_delaySender.SafeDispose();
- this.m_delaySender = new DelaySender(this.MainSocket, senderOption.QueueLength, this.OnDelaySenderError)
- {
- DelayLength = senderOption.DelayLength
- };
- }
- this.BeginReceive();
- this.PrivateOnConnected(new MsgEventArgs("连接成功"));
- return;
- }
- else
- {
- this.MainSocket.SafeDispose();
- throw new Exception("异步已完成,但是socket并未在连接状态,可能发生了绑定端口占用的错误。");
- }
- }
- this.MainSocket.SafeDispose();
- throw new TimeoutException();
- }
- }
- }
- /// <summary>
- /// 请求连接到服务器。
- /// </summary>
- public virtual ITcpClient Connect(int timeout = 5000)
- {
- this.TcpConnect(timeout);
- return this;
- }
- /// <summary>
- /// 异步连接服务器
- /// </summary>
- public Task<ITcpClient> ConnectAsync(int timeout = 5000)
- {
- return EasyTask.Run(() =>
- {
- return this.Connect(timeout);
- });
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <returns></returns>
- public Stream GetStream()
- {
- if (this.m_workStream == null)
- {
- this.m_workStream = new NetworkStream(this.MainSocket, true);
- }
- return this.m_workStream;
- }
- /// <summary>
- /// 设置数据处理适配器
- /// </summary>
- /// <param name="adapter"></param>
- public virtual void SetDataHandlingAdapter(DataHandlingAdapter adapter)
- {
- if (!this.CanSetDataHandlingAdapter)
- {
- throw new Exception($"不允许自由调用{nameof(SetDataHandlingAdapter)}进行赋值。");
- }
- this.SetAdapter(adapter);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="ipHost"></param>
- /// <returns></returns>
- public ITcpClient Setup(string ipHost)
- {
- TouchSocketConfig config = new TouchSocketConfig();
- config.SetRemoteIPHost(new IPHost(ipHost));
- return this.Setup(config);
- }
- /// <summary>
- /// 配置服务器
- /// </summary>
- /// <param name="config"></param>
- /// <exception cref="Exception"></exception>
- public ITcpClient Setup(TouchSocketConfig config)
- {
- this.Config = config;
- this.PluginsManager = config.PluginsManager;
- if (config.IsUsePlugin)
- {
- this.PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
- }
- this.LoadConfig(this.Config);
- if (this.UsePlugin)
- {
- this.PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
- }
- return this;
- }
- private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- if (this.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
- {
- return;
- }
- if (this.UsePlugin)
- {
- ReceivedDataEventArgs args = new ReceivedDataEventArgs(byteBlock, requestInfo);
- this.PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnReceivedData), this, args);
- if (args.Handled)
- {
- return;
- }
- }
- this.HandleReceivedData(byteBlock, requestInfo);
- }
- /// <summary>
- /// 处理已接收到的数据。
- /// </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 (this.UsePlugin)
- {
- SendingEventArgs args = new SendingEventArgs(buffer, offset, length);
- this.PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnSendingData), this, args);
- if (args.IsPermitOperation)
- {
- return true;
- }
- return false;
- }
- return true;
- }
- /// <summary>
- /// 加载配置
- /// </summary>
- /// <param name="config"></param>
- protected virtual void LoadConfig(TouchSocketConfig config)
- {
- if (config == null)
- {
- throw new Exception("配置文件为空");
- }
- this.RemoteIPHost = config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
- this.BufferLength = config.GetValue(TouchSocketConfigExtension.BufferLengthProperty);
- this.ReceiveType = config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty);
- this.UsePlugin = config.IsUsePlugin;
- this.Logger = this.Container.Resolve<ILog>();
- if (config.GetValue(TouchSocketConfigExtension.SslOptionProperty) != null)
- {
- this.UseSsl = true;
- }
- }
- /// <summary>
- /// 在延迟发生错误
- /// </summary>
- /// <param name="ex"></param>
- protected virtual void OnDelaySenderError(Exception ex)
- {
- this.Logger.Log(LogType.Error, this, "发送错误", ex);
- }
- /// <summary>
- /// 设置适配器,该方法不会检验<see cref="CanSetDataHandlingAdapter"/>的值。
- /// </summary>
- /// <param name="adapter"></param>
- protected void SetAdapter(DataHandlingAdapter adapter)
- {
- if (adapter is null)
- {
- throw new ArgumentNullException(nameof(adapter));
- }
- if (this.Config != null)
- {
- if (this.Config.GetValue(TouchSocketConfigExtension.MaxPackageSizeProperty) is int v1)
- {
- adapter.MaxPackageSize = v1;
- }
- if (this.Config.GetValue(TouchSocketConfigExtension.CacheTimeoutProperty) != TimeSpan.Zero)
- {
- adapter.CacheTimeout = this.Config.GetValue(TouchSocketConfigExtension.CacheTimeoutProperty);
- }
- if (this.Config.GetValue(TouchSocketConfigExtension.CacheTimeoutEnableProperty) is bool v2)
- {
- adapter.CacheTimeoutEnable = v2;
- }
- if (this.Config.GetValue(TouchSocketConfigExtension.UpdateCacheTimeWhenRevProperty) is bool v3)
- {
- adapter.UpdateCacheTimeWhenRev = v3;
- }
- }
- adapter.OnLoaded(this);
- adapter.ReceivedCallBack = this.PrivateHandleReceivedData;
- adapter.SendCallBack = this.DefaultSend;
- this.DataHandlingAdapter = adapter;
- }
- private void BeginReceive()
- {
- this.m_workStream.SafeDispose();
- if (this.UseSsl)
- {
- ClientSslOption sslOption = (ClientSslOption)this.Config.GetValue(TouchSocketConfigExtension.SslOptionProperty);
- SslStream sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.MainSocket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.MainSocket, false), false);
- if (sslOption.ClientCertificates == null)
- {
- sslStream.AuthenticateAsClient(sslOption.TargetHost);
- }
- else
- {
- sslStream.AuthenticateAsClient(sslOption.TargetHost, sslOption.ClientCertificates, sslOption.SslProtocols, sslOption.CheckCertificateRevocation);
- }
- this.m_workStream = sslStream;
- if (this.ReceiveType != ReceiveType.None)
- {
- this.BeginSsl();
- }
- }
- else
- {
- if (this.ReceiveType == ReceiveType.Auto)
- {
- SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
- eventArgs.Completed += this.EventArgs_Completed;
- ByteBlock byteBlock = BytePool.Default.GetByteBlock(this.BufferLength);
- eventArgs.UserToken = byteBlock;
- eventArgs.SetBuffer(byteBlock.Buffer, 0, byteBlock.Buffer.Length);
- if (!this.MainSocket.ReceiveAsync(eventArgs))
- {
- this.ProcessReceived(eventArgs);
- }
- }
- }
- }
- private void BeginSsl()
- {
- ByteBlock byteBlock = new ByteBlock(this.BufferLength);
- try
- {
- this.m_workStream.BeginRead(byteBlock.Buffer, 0, byteBlock.Capacity, this.EndSsl, byteBlock);
- }
- catch (Exception ex)
- {
- byteBlock.Dispose();
- this.BreakOut(ex.Message, false);
- }
- }
- private void EndSsl(IAsyncResult result)
- {
- ByteBlock byteBlock = (ByteBlock)result.AsyncState;
- try
- {
- int r = this.m_workStream.EndRead(result);
- if (r == 0)
- {
- this.BreakOut("远程终端主动关闭", false);
- }
- byteBlock.SetLength(r);
- this.HandleBuffer(byteBlock);
- this.BeginSsl();
- }
- catch (System.Exception ex)
- {
- byteBlock.Dispose();
- this.BreakOut(ex.Message, false);
- }
- }
- private Socket CreateSocket(IPHost iPHost)
- {
- Socket socket = new Socket(iPHost.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
- socket.ReceiveBufferSize = this.BufferLength;
- socket.SendBufferSize = this.BufferLength;
- #if NET45_OR_GREATER
- KeepAliveValue keepAliveValue = this.Config.GetValue<KeepAliveValue>(TouchSocketConfigExtension.KeepAliveValueProperty);
- if (keepAliveValue.Enable)
- {
- socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
- socket.IOControl(IOControlCode.KeepAliveValues, keepAliveValue.KeepAliveTime, null);
- }
- #else
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- KeepAliveValue keepAliveValue = Config.GetValue<KeepAliveValue>(TouchSocketConfigExtension.KeepAliveValueProperty);
- if (keepAliveValue.Enable)
- {
- socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
- socket.IOControl(IOControlCode.KeepAliveValues, keepAliveValue.KeepAliveTime, null);
- }
- }
- #endif
- socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, this.Config.GetValue<bool>(TouchSocketConfigExtension.NoDelayProperty));
- if (this.Config.GetValue<IPHost>(TouchSocketConfigExtension.BindIPHostProperty) != null)
- {
- if (this.Config.GetValue<bool>(TouchSocketConfigExtension.ReuseAddressProperty))
- {
- socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- }
- socket.Bind(this.Config.GetValue<IPHost>(TouchSocketConfigExtension.BindIPHostProperty).EndPoint);
- }
- return socket;
- }
- private void EventArgs_Completed(object sender, SocketAsyncEventArgs e)
- {
- try
- {
- this.ProcessReceived(e);
- }
- catch (System.Exception ex)
- {
- e.Dispose();
- this.BreakOut(ex.Message, false);
- }
- }
- /// <summary>
- /// 处理数据
- /// </summary>
- private void HandleBuffer(ByteBlock byteBlock)
- {
- try
- {
- this.LastReceivedTime = DateTime.Now;
- if (this.OnHandleRawBuffer?.Invoke(byteBlock) == false)
- {
- return;
- }
- if (this.DisposedValue)
- {
- return;
- }
- if (this.UsePlugin && this.PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnReceivingData), this, new ByteBlockEventArgs(byteBlock)))
- {
- return;
- }
- if (this.DataHandlingAdapter == null)
- {
- this.Logger.Error(this, TouchSocketStatus.NullDataAdapter.GetDescription());
- return;
- }
- this.DataHandlingAdapter.ReceivedInput(byteBlock);
- }
- catch (Exception ex)
- {
- this.Logger.Log(LogType.Error, this, "在处理数据时发生错误", ex);
- }
- finally
- {
- byteBlock.Dispose();
- }
- }
- #region 发送
- #region 同步发送
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="requestInfo"></param>
- /// <exception cref="NotConnectedException"></exception>
- /// <exception cref="OverlengthException"></exception>
- /// <exception cref="Exception"></exception>
- public void Send(IRequestInfo requestInfo)
- {
- if (this.DisposedValue)
- {
- return;
- }
- if (this.DataHandlingAdapter == null)
- {
- throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
- }
- if (!this.DataHandlingAdapter.CanSendRequestInfo)
- {
- throw new NotSupportedException($"当前适配器不支持对象发送。");
- }
- this.DataHandlingAdapter.SendInput(requestInfo);
- }
- /// <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 virtual void Send(byte[] buffer, int offset, int length)
- {
- if (this.DataHandlingAdapter == null)
- {
- throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
- }
- this.DataHandlingAdapter.SendInput(buffer, offset, length);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="transferBytes"><inheritdoc/></param>
- /// <exception cref="NotConnectedException"><inheritdoc/></exception>
- /// <exception cref="OverlengthException"><inheritdoc/></exception>
- /// <exception cref="Exception"><inheritdoc/></exception>
- public virtual void Send(IList<ArraySegment<byte>> transferBytes)
- {
- if (this.DataHandlingAdapter == null)
- {
- throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
- }
- if (this.DataHandlingAdapter.CanSplicingSend)
- {
- this.DataHandlingAdapter.SendInput(transferBytes);
- }
- else
- {
- ByteBlock byteBlock = BytePool.Default.GetByteBlock(this.BufferLength);
- try
- {
- foreach (var item in transferBytes)
- {
- byteBlock.Write(item.Array, item.Offset, item.Count);
- }
- this.DataHandlingAdapter.SendInput(byteBlock.Buffer, 0, byteBlock.Len);
- }
- finally
- {
- byteBlock.Dispose();
- }
- }
- }
- #endregion 同步发送
- #region 异步发送
- /// <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 virtual Task SendAsync(byte[] buffer, int offset, int length)
- {
- return EasyTask.Run(() =>
- {
- this.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(() =>
- {
- this.Send(requestInfo);
- });
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="transferBytes"><inheritdoc/></param>
- /// <exception cref="NotConnectedException"><inheritdoc/></exception>
- /// <exception cref="OverlengthException"><inheritdoc/></exception>
- /// <exception cref="Exception"><inheritdoc/></exception>
- public virtual Task SendAsync(IList<ArraySegment<byte>> transferBytes)
- {
- return EasyTask.Run(() =>
- {
- this.Send(transferBytes);
- });
- }
- #endregion 异步发送
- /// <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 void DefaultSend(byte[] buffer, int offset, int length)
- {
- if (!this.CanSend)
- {
- throw new NotConnectedException(TouchSocketStatus.NotConnected.GetDescription());
- }
- if (this.HandleSendingData(buffer, offset, length))
- {
- if (this.UseSsl)
- {
- this.m_workStream.Write(buffer, offset, length);
- }
- else
- {
- if (this.m_useDelaySender && length < TouchSocketUtility.BigDataBoundary)
- {
- this.m_delaySender.Send(new QueueDataBytes(buffer, offset, length));
- }
- else
- {
- this.MainSocket.AbsoluteSend(buffer, offset, length);
- }
- }
- this.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(() =>
- {
- this.DefaultSend(buffer, offset, length);
- });
- }
- #endregion 发送
- private void LoadSocketAndReadIpPort()
- {
- if (this.MainSocket == null)
- {
- this.IP = null;
- this.Port = -1;
- return;
- }
- string ipport;
- if (this.MainSocket.Connected && this.MainSocket.RemoteEndPoint != null)
- {
- ipport = this.MainSocket.RemoteEndPoint.ToString();
- }
- else if (this.MainSocket.IsBound && this.MainSocket.LocalEndPoint != null)
- {
- ipport = this.MainSocket.LocalEndPoint.ToString();
- }
- else
- {
- return;
- }
- int r = ipport.LastIndexOf(":");
- this.IP = ipport.Substring(0, r);
- this.Port = Convert.ToInt32(ipport.Substring(r + 1, ipport.Length - (r + 1)));
- }
- private void ProcessReceived(SocketAsyncEventArgs e)
- {
- if (!this.CanSend)
- {
- e.Dispose();
- return;
- }
- if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
- {
- ByteBlock byteBlock = (ByteBlock)e.UserToken;
- byteBlock.SetLength(e.BytesTransferred);
- this.HandleBuffer(byteBlock);
- try
- {
- ByteBlock newByteBlock = BytePool.Default.GetByteBlock(this.BufferLength);
- e.UserToken = newByteBlock;
- e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Buffer.Length);
- if (!this.MainSocket.ReceiveAsync(e))
- {
- this.ProcessReceived(e);
- }
- }
- catch (System.Exception ex)
- {
- e.Dispose();
- this.BreakOut(ex.Message, false);
- }
- }
- else
- {
- e.Dispose();
- this.BreakOut("远程终端主动关闭", false);
- }
- }
- }
- }
|