//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在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.Concurrent; using System.Collections.Generic; using System.Net; using System.Threading; using TouchSocket.Core; namespace TouchSocket.Sockets { /// /// UDP数据帧 /// public struct UdpFrame { /// /// Crc校验 /// public byte[] Crc { get; set; } /// /// 数据 /// public byte[] Data { get; set; } /// /// 是否为终结帧 /// public bool FIN { get; set; } /// /// 数据ID /// public long ID { get; set; } /// /// 帧序号 /// public ushort SN { get; set; } /// /// 解析 /// /// /// /// /// public bool Parse(byte[] buffer, int offset, int length) { if (length > 11) { this.ID = TouchSocketBitConverter.Default.ToInt64(buffer, offset); this.SN = TouchSocketBitConverter.Default.ToUInt16(buffer, 8 + offset); this.FIN = buffer[10 + offset].GetBit(7) == 1; if (this.FIN) { if (length > 13) { this.Data = new byte[length - 13]; } else { this.Data = new byte[0]; } this.Crc = new byte[2] { buffer[length - 2], buffer[length - 1] }; } else { this.Data = new byte[length - 11]; } Array.Copy(buffer, 11, this.Data, 0, this.Data.Length); return true; } return false; } } /// /// UDP数据包 /// [System.Diagnostics.DebuggerDisplay("Count={Count}")] public class UdpPackage { private readonly ConcurrentQueue m_frames; private readonly Timer m_timer; private int m_count; private int m_length; private int m_mtu; /// /// 构造函数 /// /// /// /// public UdpPackage(long id, int timeout, ConcurrentDictionary revStore) { this.ID = id; this.m_frames = new ConcurrentQueue(); this.m_timer = new Timer((o) => { if (revStore.TryRemove(this.ID, out UdpPackage udpPackage)) { udpPackage.m_frames.Clear(); } }, null, timeout, Timeout.Infinite); } /// /// 当前长度 /// public int Count => this.m_count; /// /// Crc /// public byte[] Crc { get; private set; } /// /// 包唯一标识 /// public long ID { get; } /// /// 是否已完成 /// public bool IsComplated => this.TotalCount > 0 ? (this.TotalCount == this.m_count ? true : false) : false; /// /// 当前数据长度 /// public int Length => this.m_length; /// /// MTU /// public int MTU => this.m_mtu + 11; /// /// 总长度,在收到最后一帧之前,为-1。 /// public int TotalCount { get; private set; } = -1; /// /// 添加帧 /// /// public void Add(UdpFrame frame) { Interlocked.Increment(ref this.m_count); if (frame.FIN) { this.TotalCount = frame.SN + 1; this.Crc = frame.Crc; } Interlocked.Add(ref this.m_length, frame.Data.Length); if (frame.SN == 0) { this.m_mtu = frame.Data.Length; } this.m_frames.Enqueue(frame); } /// /// 获得数据 /// /// /// public bool TryGetData(ByteBlock byteBlock) { while (this.m_frames.TryDequeue(out UdpFrame frame)) { byteBlock.Pos = frame.SN * this.m_mtu; byteBlock.Write(frame.Data); } if (byteBlock.Len != this.Length) { return false; } byte[] crc = TouchSocket.Core.Crc.Crc16(byteBlock.Buffer, 0, byteBlock.Len); if (crc[0] != this.Crc[0] || crc[1] != this.Crc[1]) { return false; } return true; } } /// /// UDP数据包的适配器 /// public class UdpPackageAdapter : UdpDataHandlingAdapter { private readonly SnowflakeIDGenerator m_iDGenerator; private readonly ConcurrentDictionary revStore; private int m_mtu = 1472; /// /// 构造函数 /// public UdpPackageAdapter() { this.revStore = new ConcurrentDictionary(); this.m_iDGenerator = new SnowflakeIDGenerator(4); } /// /// /// public override bool CanSendRequestInfo => false; /// /// /// public override bool CanSplicingSend => true; /// /// 最大传输单元 /// public int MTU { get => this.m_mtu + 11; set => this.m_mtu = value > 11 ? value : 1472; } /// /// 接收超时时间,默认5000ms /// public int Timeout { get; set; } = 5000; /// /// /// /// /// protected override void PreviewReceived(EndPoint remoteEndPoint, ByteBlock byteBlock) { var udpFrame = new UdpFrame(); if (udpFrame.Parse(byteBlock.Buffer, 0, byteBlock.Len)) { UdpPackage udpPackage = this.revStore.GetOrAdd(udpFrame.ID, (i) => new UdpPackage(i, this.Timeout, this.revStore)); udpPackage.Add(udpFrame); if (udpPackage.Length > this.MaxPackageSize) { this.revStore.TryRemove(udpPackage.ID, out _); this.m_owner?.Logger.Error("数据长度大于设定的最大值。"); return; } if (udpPackage.IsComplated) { if (this.revStore.TryRemove(udpPackage.ID, out _)) { using (var block = new ByteBlock(udpPackage.Length)) { if (udpPackage.TryGetData(block)) { this.GoReceived(remoteEndPoint, block, null); } } } } } } /// /// /// /// /// /// /// protected override void PreviewSend(EndPoint endPoint, byte[] buffer, int offset, int length) { if (length > this.MaxPackageSize) { throw new OverlengthException("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送"); } long id = this.m_iDGenerator.NextID(); int off = 0; int surLen = length; int freeRoom = this.m_mtu - 11; ushort sn = 0; /*|********|**|*|n|*/ /*|********|**|*|**|*/ while (surLen > 0) { byte[] data = new byte[this.m_mtu]; Buffer.BlockCopy(TouchSocketBitConverter.Default.GetBytes(id), 0, data, 0, 8); Buffer.BlockCopy(TouchSocketBitConverter.Default.GetBytes(sn++), 0, data, 8, 2); if (surLen > freeRoom)//有余 { Buffer.BlockCopy(buffer, off, data, 11, freeRoom); off += freeRoom; surLen -= freeRoom; this.GoSend(endPoint, data, 0, this.m_mtu); } else if (surLen + 2 <= freeRoom)//结束且能容纳Crc { byte flag = 0; data[10] = flag.SetBit(7, 1);//设置终结帧 Buffer.BlockCopy(buffer, off, data, 11, surLen); Buffer.BlockCopy(Crc.Crc16(buffer, offset, length), 0, data, 11 + surLen, 2); this.GoSend(endPoint, data, 0, surLen + 11 + 2); off += surLen; surLen -= surLen; } else//结束但不能容纳Crc { Buffer.BlockCopy(buffer, off, data, 11, surLen); this.GoSend(endPoint, data, 0, surLen + 11); off += surLen; surLen -= surLen; byte[] finData = new byte[13]; Buffer.BlockCopy(TouchSocketBitConverter.Default.GetBytes(id), 0, finData, 0, 8); Buffer.BlockCopy(TouchSocketBitConverter.Default.GetBytes(sn++), 0, finData, 8, 2); byte flag = 0; finData[10] = flag.SetBit(7, 1); Buffer.BlockCopy(Crc.Crc16(buffer, offset, length), 0, finData, 11, 2); this.GoSend(endPoint, finData, 0, finData.Length); } } } /// /// /// /// /// protected override void PreviewSend(EndPoint endPoint, IList> transferBytes) { int length = 0; foreach (ArraySegment item in transferBytes) { length += item.Count; } if (length > this.MaxPackageSize) { throw new OverlengthException("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送"); } using (var byteBlock = new ByteBlock(length)) { foreach (ArraySegment item in transferBytes) { byteBlock.Write(item.Array, item.Offset, item.Count); } this.PreviewSend(endPoint, byteBlock.Buffer, 0, byteBlock.Len); } } /// /// /// /// protected override void PreviewSend(IRequestInfo requestInfo) { throw new NotImplementedException(); } /// /// /// protected override void Reset() { } } }