首页 技术 正文
技术 2022年11月8日
0 收藏 536 点赞 1,298 浏览 8981 个字

原文网址: http://www.cnblogs.com/csdev

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是:Apache License v2

开源地址是:https://github.com/MarcFletcher/NetworkComms.Net

数据包创建器   通信框架接收到的二进制数据存储到数据包创建器中  如果创建器中的数据足够多 即能够合成一个数据包  则从创建器中提取出去解析出数据包

namespace NetworkCommsDotNet.Tools{    /// <summary>    /// Packet data is generally broken into multiple variable sized byte chunks or 'partial packets'.    /// This class provides features to effortlessly rebuild whole packets.    /// 数据包创建器   通信框架接收到的二进制数据存储到数据包创建器中  如果创建器中的数据足够多 即能够合成一个数据包  则从创建器中提取出去解析出数据包    /// 解析完成后  创建器中相应的二进制数据会删除    /// 创建器好比一个流动的容器    /// </summary>    public class PacketBuilder    {        List<byte[]> packets = new List<byte[]>();        List<int> packetActualBytes = new List<int>();        /// <summary>        /// Locker object used for performing thread safe operations over this packet builder        /// 同步锁        /// </summary>        public object Locker { get; private set; }        ;        ;        /// <summary>        /// Create a new instance of the ConnectionPacketBuilder class        /// 构造函数        /// </summary>        public PacketBuilder()        {            Locker = new object();        }        /// <summary>        /// The total number of cached bytes. This is the sum of all bytes across all cached partial packets. See <see cref="TotalPartialPacketCount"/>.        /// 已经收到的数据大小        /// </summary>        public int TotalBytesCached        {            get { return totalBytesCached; }        }        /// <summary>        /// The total number of cached partial packets. This is different from <see cref="TotalBytesCached"/> because each partial packet may contain a variable number of bytes.        /// 数据包创建器中收到了多少个字节数组        /// </summary>        public int TotalPartialPacketCount        {            get { lock (Locker) return packets.Count; }        }        /// <summary>        /// The total number of bytes required to rebuild the next whole packet.        /// 当期期望收到的数(即当前接收的数据包的大小) 如果PacketBuilder中的数据足够一个数据包的大小  则进行下一步解析         /// </summary>        public int TotalBytesExpected        {            get { lock (Locker) return totalBytesExpected; }            set { lock (Locker) totalBytesExpected = value; }        }        /// <summary>        /// Clear N bytes from cache, starting with oldest bytes first.        /// 从缓存中删除N个字节  这个功能一般是解析完成当前数据包后,删除相应的二进制数据        /// </summary>        /// <param name="numBytesToRemove">The total number of bytes to be removed.</param>        public void ClearNTopBytes(int numBytesToRemove)        {            lock (Locker)            {                )                {                    if (numBytesToRemove > totalBytesCached)                        throw new CommunicationException("Attempting to remove " + numBytesToRemove.ToString() + " bytes when ConnectionPacketBuilder only contains " + totalBytesCached.ToString());                    ;                    //We will always remove bytes in order of the entries                    //按次序删除                    ; i < packets.Count; i++)                    {                        if (packetActualBytes[i] > numBytesToRemove - bytesRemoved)                        {                            //Remove the necessary bytes from this packet and rebuild                            //New array length is the original length minus the amount we need to remove                            //从字节数据组中删除相应的数据  比如删除数组的前一部分 保留后一部分  需要对数组进行重建                            byte[] newPacketByteArray = new byte[packetActualBytes[i] - (numBytesToRemove - bytesRemoved)];                            Buffer.BlockCopy(packets[i], numBytesToRemove - bytesRemoved, newPacketByteArray, , newPacketByteArray.Length);                            bytesRemoved += packetActualBytes[i] - newPacketByteArray.Length;                            packets[i] = newPacketByteArray;                            packetActualBytes[i] = newPacketByteArray.Length;                            //Stop removing data here                            //停止删除                            break;                        }                        )                        {                            //When i == (packet.Count - 1) I would expect the above if condition to always be true                            throw new CommunicationException("This should be impossible.");                        }                        else                        {                            //If we want to remove this entire packet we can just set the list reference to null                            //如果删除当前数组的所有数据  只要把数组指向null即可                            bytesRemoved += packetActualBytes[i];                            packets[i] = null;                            packetActualBytes[i] = -;                        }                    }                    if (bytesRemoved != numBytesToRemove)                        throw new CommunicationException("bytesRemoved should really equal the requested numBytesToRemove");                    //Reset the totalBytesRead                    //从已经缓存数中减去此次删除的数                    totalBytesCached -= bytesRemoved;                    )                    {                        //Get rid of any null packets                        //清除空的字节数组                        List<byte[]> newPackets = new List<byte[]>(packets.Count);                        ; i < packets.Count; i++)                        {                            if (packets[i] != null)                                newPackets.Add(packets[i]);                        }                        packets = newPackets;                        //Remove any -1 entries                        //清除值为-1的记数                        List<int> newPacketActualBytes = new List<int>(packetActualBytes.Count);                        ; i < packetActualBytes.Count; i++)                        {                            )                                newPacketActualBytes.Add(packetActualBytes[i]);                        }                        packetActualBytes = newPacketActualBytes;                    }                    else                    {                        //This is faster if we have removed everything                        //如果我们删除了所有数据 可以如下操作                        packets = new List<byte[]>();                        packetActualBytes = new List<int>();                    }                    //This is a really bad place to put a garbage collection as it hammers the CPU                    //GC.Collect();                    //不应启用垃圾收集                }                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... removed " + numBytesToRemove + " bytes from packetBuilder.");            }        }        /// <summary>        /// Add a partial packet to the end of the cache by reference.        /// 添加数据到相应的数据组        /// </summary>        /// <param name="packetBytes">字节数量  The number of valid bytes in the provided partial packet</param>        /// <param name="partialPacket">相关字节  A buffer which may or may not be full with valid bytes</param>        public void AddPartialPacket(int packetBytes, byte[] partialPacket)        {            if (packetBytes > partialPacket.Length)                throw new ArgumentException("packetBytes cannot be greater than the length of the provided partialPacket data.");            )                throw new ArgumentException("packetBytes cannot be negative.");            lock (Locker)            {                totalBytesCached += packetBytes;                packets.Add(partialPacket);                packetActualBytes.Add(packetBytes);                if (NetworkComms.LoggingEnabled)                {                     && totalBytesCached > ( *  * ))                        NetworkComms.Logger.Warn("Packet builder cache contains " + (totalBytesCached / 1024.0).ToString("0.0") + "KB when 0KB are currently expected.");                     && totalBytesCached > totalBytesExpected * )                        NetworkComms.Logger.Warn("Packet builder cache contains " + (totalBytesCached / 1024.0).ToString("0.0") + "KB when only " + (TotalBytesExpected / 1024.0).ToString("0.0") + "KB were expected.");                }                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... added " + packetBytes + " bytes to packetBuilder.");            }        }        /// <summary>        /// Returns the most recently cached partial packet and removes it from the cache.        /// Used to more efficiently utilise allocated memory space.        /// 返回最后一个字节数组中的数据        /// 并从创建器中删除相应的数组和记数        /// </summary>        /// <param name="lastPacketBytesRead">The number of valid bytes in the last partial packet added</param>        /// <returns>A byte[] corresponding with the last added partial packet</returns>        public byte[] RemoveMostRecentPartialPacket(ref int lastPacketBytesRead)        {            lock (Locker)            {                )                {                    ;                    lastPacketBytesRead = packetActualBytes[lastPacketIndex];                    byte[] returnArray = packets[lastPacketIndex];                    totalBytesCached -= packetActualBytes[lastPacketIndex];                    packets.RemoveAt(lastPacketIndex);                    packetActualBytes.RemoveAt(lastPacketIndex);                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... reusing byte[" + returnArray.Length + "] from packetBuilder which contains " + lastPacketBytesRead + " existing bytes.");                    return returnArray;                }                else                    throw new Exception("Unable to remove most recent packet as packet list is empty.");            }        }        /// <summary>        /// Returns the number of unused bytes in the most recently cached partial packet.        /// 返回在最近的缓存部分包未使用的字节数。        /// </summary>        /// <returns>The number of unused bytes in the most recently cached partial packet.</returns>        public int NumUnusedBytesMostRecentPartialPacket()        {            lock (Locker)            {                )                {                    ;                    return packets[lastPacketIndex].Length - packetActualBytes[lastPacketIndex];                }                else                    throw new Exception("Unable to return requested size as packet list is empty.");            }        }        /// <summary>        /// Returns the value of the first cached byte.        /// 返回第一个缓存的字节的值。        /// </summary>        /// <returns>The value of the first cached byte.</returns>        public byte FirstByte()        {            lock (Locker)                ][];        }        /// <summary>        /// Copies all cached bytes into a single array and returns. Original data is left unchanged.        /// 把所有数据复制到一维数组中并返回   原始数据保持不变。        /// </summary>        /// <returns>All cached data as a single byte[]</returns>        public byte[] GetAllData()        {            lock (Locker)            {                byte[] returnArray = new byte[totalBytesCached];                ;                ; i < packets.Count; i++)                {                    Buffer.BlockCopy(packets[i], , returnArray, currentStart, packetActualBytes[i]);                    currentStart += packetActualBytes[i];                }                return returnArray;            }        }        /// <summary>        /// Copies the requested cached bytes into a single array and returns. Original data is left unchanged.        /// 根据参数 返回请求的数据 原始数据不变        /// </summary>        /// <param name="startIndex">开始位置  The inclusive byte index to use as the starting position.</param>        /// <param name="length">长度  The total number of desired bytes.</param>        /// <returns>The requested bytes as a single array.</returns>        public MemoryStream ReadDataSection(int startIndex, int length)        {            lock (Locker)            {                byte[] returnArray = new byte[length];                , writeTotal = ;                int startingPacketIndex;                ;                //First find the correct starting packet                //找到正确的字节数组的相应位置                ; startingPacketIndex < packets.Count; startingPacketIndex++)                {                    if (startIndex - runningTotal <= packetActualBytes[startingPacketIndex])                    {                        firstPacketStartIndex = startIndex - runningTotal;                        break;                    }                    else                        runningTotal += packetActualBytes[startingPacketIndex];                }                //Copy the bytes of interest                //复制感兴趣的字节数据                for (int i = startingPacketIndex; i < packets.Count; i++)                {                    if (i == startingPacketIndex)                    {                        if (length > packetActualBytes[i] - firstPacketStartIndex)                            //If we want from some starting point to the end of the packet  从字节数组的某个位置开始                            Buffer.BlockCopy(packets[i], firstPacketStartIndex, returnArray, writeTotal, packetActualBytes[i] - firstPacketStartIndex);                        else                        {                            //We only want part of the packet  整个字节数组                            Buffer.BlockCopy(packets[i], firstPacketStartIndex, returnArray, writeTotal, length);                            writeTotal += length;                            break;                        }                        writeTotal = packetActualBytes[i] - firstPacketStartIndex;                    }                    else                    {                        //We are no longer on the first packet 不在第一个数据包上                        if (packetActualBytes[i] + writeTotal >= length)                        {                            //We have reached the last packet of interest 已经到达我们希望到达的最后一个数据包                            Buffer.BlockCopy(packets[i], , returnArray, writeTotal, length - writeTotal);                            writeTotal += length - writeTotal;                            break;                        }                        else                        {                            Buffer.BlockCopy(packets[i], , returnArray, writeTotal, packetActualBytes[i]);                            writeTotal += packetActualBytes[i];                        }                    }                }                if (writeTotal != length) throw new Exception("Not enough data available in packetBuilder to complete request. Requested " + length.ToString() + " bytes but only " + writeTotal.ToString() + " bytes were copied.");#if NETFX_CORE                , returnArray.Length, false);#else                , returnArray.Length, false, true);#endif            }        }    }}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,942
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,468
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,281
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,095
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,728
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,765