//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在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 TouchSocket.Core; namespace TouchSocket.Sockets { /// /// 大数据用户自定义固定包头解析器,使用该适配器时,接收方收到的数据中,将为null,同时将实现为TFixedHeaderRequestInfo。 /// public abstract class CustomBigFixedHeaderDataHandlingAdapter : CustomDataHandlingAdapter where TFixedHeaderRequestInfo : class, IBigFixedHeaderRequestInfo { /// /// 固定包头的长度。 /// public abstract int HeaderLength { get; } /// /// 筛选解析数据。实例化的TRequest会一直保存,直至解析成功,或手动清除。 /// 当不满足解析条件时,请返回,此时会保存的数据 /// 当数据部分异常时,请移动到指定位置,然后返回 /// 当完全满足解析条件时,请返回最后将移至指定位置。 /// /// 字节块 /// 是否为上次遗留对象,当该参数为True时,request也将是上次实例化的对象。 /// 对象。 /// 缓存容量。当需要首次缓存时,指示申请的ByteBlock的容量。合理的值可避免ByteBlock扩容带来的性能消耗。 /// protected override FilterResult Filter(ByteBlock byteBlock, bool beCached, ref TFixedHeaderRequestInfo request, ref int tempCapacity) { if (beCached) { while (this.m_surLen > 0 && byteBlock.CanRead) { int r = (int)Math.Min(this.m_surLen, byteBlock.CanReadLength); try { request.OnAppendBody(byteBlock.Buffer, byteBlock.Pos, r); this.m_surLen -= r; byteBlock.Pos += r; if (this.m_surLen == 0) { if (request.OnFinished()) { return FilterResult.Success; } request = null; return FilterResult.GoOn; } } catch (Exception ex) { this.OnError(ex.Message, false, true); } } return FilterResult.GoOn; } else { if (this.HeaderLength > byteBlock.CanReadLen) { return FilterResult.Cache; } TFixedHeaderRequestInfo requestInfo = this.GetInstance(); byteBlock.Read(out byte[] header, this.HeaderLength); if (requestInfo.OnParsingHeader(header)) { request = requestInfo; if (requestInfo.BodyLength == 0) { if (requestInfo.OnFinished()) { return FilterResult.Success; } request = null; return FilterResult.GoOn; } this.m_surLen = request.BodyLength; while (this.m_surLen > 0 && byteBlock.CanRead) { int r = (int)Math.Min(this.m_surLen, byteBlock.CanReadLength); try { request.OnAppendBody(byteBlock.Buffer, byteBlock.Pos, r); this.m_surLen -= r; byteBlock.Pos += r; if (this.m_surLen == 0) { if (request.OnFinished()) { return FilterResult.Success; } request = null; return FilterResult.GoOn; } } catch (Exception ex) { this.OnError(ex.Message, false, true); } } return FilterResult.GoOn; } else { return FilterResult.GoOn; } } } private long m_surLen; /// /// 获取泛型实例。 /// /// protected abstract TFixedHeaderRequestInfo GetInstance(); } /// /// 用户自定义固定包头请求 /// public interface IBigFixedHeaderRequestInfo : IRequestInfo { /// /// 数据体长度 /// long BodyLength { get; } /// /// 当收到数据,由框架封送固定协议头。 /// 您需要在此函数中,解析自己的固定包头,并且对赋值后续数据的长度,然后返回True。 /// 如果返回false,则意味着放弃本次解析 /// /// /// bool OnParsingHeader(byte[] header); /// /// 当收到数据,由框架封送数据。 /// 您需要将有效数据自行保存。该方法可能会多次调用。 /// /// /// /// /// 是否成功有效 void OnAppendBody(byte[] buffer, int offset, int length); /// /// 当完成数据接收时调用。 /// 当返回False时,将不会把该对象向Received传递。 /// /// 是否成功有效 bool OnFinished(); } }