//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在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 TouchSocket.Core; namespace TouchSocket.Sockets { /// /// 用户自定义数据处理适配器,使用该适配器时,接收方收到的数据中,将为null, /// 同时将实现为TRequest,发送数据直接发送。 /// 此处设计思路借鉴SuperSocket。 /// public abstract class CustomDataHandlingAdapter : DataHandlingAdapter where TRequest : class, IRequestInfo { /// /// 缓存数据,如果需要手动释放,请先判断,然后到调用后,再置空; /// protected ByteBlock TempByteBlock; /// /// 缓存对象。 /// protected TRequest TempRequest; private bool m_needReset; /// /// /// public override bool CanSendRequestInfo => false; /// /// 默认不支持拼接发送 /// public override bool CanSplicingSend => false; /// /// 筛选解析数据。实例化的TRequest会一直保存,直至解析成功,或手动清除。 /// 当不满足解析条件时,请返回,此时会保存的数据 /// 当数据部分异常时,请移动到指定位置,然后返回 /// 当完全满足解析条件时,请返回最后将移至指定位置。 /// /// 字节块 /// 是否为上次遗留对象,当该参数为True时,request也将是上次实例化的对象。 /// 对象。 /// 缓存容量。当需要首次缓存时,指示申请的ByteBlock的容量。合理的值可避免ByteBlock扩容带来的性能消耗。 /// protected abstract FilterResult Filter(ByteBlock byteBlock, bool beCached, ref TRequest request, ref int tempCapacity); /// /// 成功执行接收以后。 /// /// protected virtual void OnReceivedSuccess(TRequest request) { } /// /// 即将执行。 /// /// /// 返回值标识是否继续执行 protected virtual bool OnReceivingSuccess(TRequest request) { return true; } /// /// /// /// protected override void PreviewReceived(ByteBlock byteBlock) { if (this.m_needReset || this.CacheTimeoutEnable && DateTime.Now - this.LastCacheTime > this.CacheTimeout) { this.Reset(); this.m_needReset = false; } if (this.TempByteBlock == null) { this.Single(byteBlock, false); } else { this.TempByteBlock.Write(byteBlock.Buffer, 0, byteBlock.Len); ByteBlock block = this.TempByteBlock; this.TempByteBlock = null; this.Single(block, true); } } /// /// /// /// protected override void PreviewSend(IRequestInfo requestInfo) { } /// /// /// /// 数据 /// 偏移 /// 长度 protected override void PreviewSend(byte[] buffer, int offset, int length) { this.GoSend(buffer, offset, length); } /// /// /// /// protected override void PreviewSend(IList> transferBytes) { throw new System.NotImplementedException();//因为设置了不支持拼接发送,所以该方法可以不实现。 } /// /// /// protected override void Reset() { this.TempByteBlock.SafeDispose(); this.TempByteBlock = null; this.TempRequest = default; this.m_needReset = true; base.Reset(); } private void Single(ByteBlock byteBlock, bool temp) { byteBlock.Pos = 0; while (byteBlock.Pos < byteBlock.Len) { if (this.m_needReset) { return; } int tempCapacity = 1024 * 64; FilterResult filterResult = this.Filter(byteBlock, this.TempRequest != null, ref this.TempRequest, ref tempCapacity); switch (filterResult) { case FilterResult.Success: if (this.OnReceivingSuccess(this.TempRequest)) { this.GoReceived(null, this.TempRequest); this.OnReceivedSuccess(this.TempRequest); } this.TempRequest = default; break; case FilterResult.Cache: if (byteBlock.CanReadLen > 0) { if (temp) { this.TempByteBlock = new ByteBlock(tempCapacity); this.TempByteBlock.Write(byteBlock.Buffer, byteBlock.Pos, byteBlock.CanReadLen); byteBlock.Dispose(); } else { this.TempByteBlock = new ByteBlock(tempCapacity); this.TempByteBlock.Write(byteBlock.Buffer, byteBlock.Pos, byteBlock.CanReadLen); } if (this.TempByteBlock.Len > this.MaxPackageSize) { this.OnError("缓存的数据长度大于设定值的情况下未收到解析信号"); } } if (this.UpdateCacheTimeWhenRev) { this.LastCacheTime = DateTime.Now; } return; case FilterResult.GoOn: if (this.UpdateCacheTimeWhenRev) { this.LastCacheTime = DateTime.Now; } break; } } } } }