123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- //------------------------------------------------------------------------------
- // 此代码版权(除特别声明或在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.Threading;
- using System.Threading.Tasks;
- using TouchSocket.Core;
- using TouchSocket.Resources;
- namespace TouchSocket.Sockets
- {
- internal class WaitingClient<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, IDefaultSender, ISender
- {
- private readonly WaitData<ResponsedData> m_waitData;
- private volatile bool breaked;
- public WaitingClient(TClient client, WaitingOptions waitingOptions)
- {
- Client = client ?? throw new ArgumentNullException(nameof(client));
- m_waitData = new WaitData<ResponsedData>();
- WaitingOptions = waitingOptions;
- }
- public bool CanSend
- {
- get
- {
- if (Client is ITcpClientBase tcpClient)
- {
- return tcpClient.Online;
- }
- else if (Client is IUdpSession)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- public TClient Client { get; private set; }
- public WaitingOptions WaitingOptions { get; set; }
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="offset">偏移</param>
- /// <param name="length">长度</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public ResponsedData SendThenResponse(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
- {
- lock (this)
- {
- try
- {
- breaked = false;
- m_waitData.Reset();
- if (WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
- {
- tcpClient.Disconnected += this.OnDisconnected;
- }
- if (WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
- {
- Client.OnHandleReceivedData += OnHandleReceivedData;
- }
- else
- {
- Client.OnHandleRawBuffer += OnHandleRawBuffer;
- }
- if (WaitingOptions.RemoteIPHost != null && Client is IUdpSession session)
- {
- if (WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
- {
- session.Send(WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
- }
- else
- {
- session.DefaultSend(WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
- }
- }
- else
- {
- if (WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
- {
- Client.Send(buffer, offset, length);
- }
- else
- {
- Client.DefaultSend(buffer, offset, length);
- }
- }
- m_waitData.SetCancellationToken(token);
- switch (m_waitData.Wait(timeout))
- {
- case WaitDataStatus.SetRunning:
- return m_waitData.WaitResult;
- case WaitDataStatus.Overtime:
- throw new TimeoutException();
- case WaitDataStatus.Canceled:
- {
- if (this.WaitingOptions.ThrowBreakException && this.breaked)
- {
- throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。");
- }
- return default;
- }
- case WaitDataStatus.Default:
- case WaitDataStatus.Disposed:
- default:
- throw new Exception(TouchSocketStatus.UnknownError.GetDescription());
- }
- }
- finally
- {
- if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
- {
- tcpClient.Disconnected -= this.OnDisconnected;
- }
- if (WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
- {
- Client.OnHandleReceivedData -= OnHandleReceivedData;
- }
- else
- {
- Client.OnHandleRawBuffer -= OnHandleRawBuffer;
- }
- }
- }
- }
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public ResponsedData SendThenResponse(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return SendThenResponse(buffer, 0, buffer.Length, timeout, token);
- }
- /// <summary>
- /// 发送流中的有效数据
- /// </summary>
- /// <param name="byteBlock">数据块载体</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public ResponsedData SendThenResponse(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return SendThenResponse(byteBlock.Buffer, 0, byteBlock.Len, timeout, token);
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="offset">偏移</param>
- /// <param name="length">长度</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return EasyTask.Run(() =>
- {
- return SendThenResponse(buffer, offset, length, timeout, token);
- });
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return EasyTask.Run(() =>
- {
- return SendThenResponse(buffer, timeout, token);
- });
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="byteBlock">数据块载体</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public Task<ResponsedData> SendThenResponseAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return EasyTask.Run(() =>
- {
- return SendThenResponse(byteBlock, timeout, token);
- });
- }
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="offset">偏移</param>
- /// <param name="length">长度</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public byte[] SendThenReturn(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return SendThenResponse(buffer, offset, length, timeout, token).Data;
- }
- /// <summary>
- /// 发送字节流
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public byte[] SendThenReturn(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return SendThenReturn(buffer, 0, buffer.Length, timeout, token);
- }
- /// <summary>
- /// 发送流中的有效数据
- /// </summary>
- /// <param name="byteBlock">数据块载体</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public byte[] SendThenReturn(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return SendThenReturn(byteBlock.Buffer, 0, byteBlock.Len, timeout, token);
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="offset">偏移</param>
- /// <param name="length">长度</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public Task<byte[]> SendThenReturnAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return EasyTask.Run(() =>
- {
- return SendThenReturn(buffer, offset, length, timeout, token);
- });
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="buffer">数据缓存区</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public Task<byte[]> SendThenReturnAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return EasyTask.Run(() =>
- {
- return SendThenReturn(buffer, timeout, token);
- });
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="byteBlock">数据块载体</param>
- /// <param name="timeout">超时时间</param>
- /// <param name="token">取消令箭</param>
- /// <exception cref="NotConnectedException">客户端没有连接</exception>
- /// <exception cref="OverlengthException">发送数据超长</exception>
- /// <exception cref="Exception">其他异常</exception>
- /// <returns>返回的数据</returns>
- public Task<byte[]> SendThenReturnAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
- {
- return EasyTask.Run(() =>
- {
- return SendThenReturn(byteBlock, timeout, token);
- });
- }
- protected override void Dispose(bool disposing)
- {
- this.Client = default;
- this.m_waitData.SafeDispose();
- base.Dispose(disposing);
- }
- private void OnDisconnected(ITcpClientBase client, DisconnectEventArgs e)
- {
- breaked = true;
- this.m_waitData.Cancel();
- }
- private bool OnHandleRawBuffer(ByteBlock byteBlock)
- {
- ResponsedData responsedData = new ResponsedData(byteBlock.ToArray(), null);
- return !m_waitData.Set(responsedData);
- }
- /// <summary>
- /// <inheritdoc/>
- /// </summary>
- /// <param name="byteBlock"></param>
- /// <param name="requestInfo"></param>
- private bool OnHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
- {
- ResponsedData responsedData;
- if (byteBlock != null)
- {
- responsedData = new ResponsedData(byteBlock.ToArray(), requestInfo);
- }
- else
- {
- responsedData = new ResponsedData(null, requestInfo);
- }
- return !m_waitData.Set(responsedData);
- }
- }
- }
|