原文网址: 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
            }
        }
    }
}

最新文章

  1. DOM官方定义
  2. VB中复制-粘贴-剪切键实现
  3. 关于(object sender, EventArgs e)
  4. Entity Framework 第九篇 关于自增列的事务处理
  5. 如何用ZBrush雕刻出栩栩如生的头发(二)
  6. mysql建库DATETIME、DATE 和 TIMESTAMP区别
  7. DOS下快速删除文件
  8. 解决IE5、IE6、IE7与W3C标准的冲突,使用(IE7.js IE8.js)兼容
  9. Java WeakReference的理解与使用
  10. python_Opencv_opencv2.4.4+python配置问题
  11. Linux 08
  12. 利用JS做到隐藏div和显示div
  13. 10--Python入门--异常处理
  14. myBatis框架之入门(一)
  15. 02 http,servlet,servletconfig,HttpServletRequest ,HttpServletResponse
  16. 检测ASP.NET是否是调试模式
  17. Loadrunner11代理录制&amp;各个常见功能介绍
  18. 帝吧fb出征是什么原因?帝吧fb出征事情始末 帝吧出征FB打“台独” 台湾网民崩溃:巨人之墙爆了
  19. 刚子扯谈:网站运营在左 技术在右 真TM扯
  20. Java跨平台的原理--java跨平台是通过JVM实现的

热门文章

  1. 换个角度理解云计算之MapReduce
  2. 初识jsonp
  3. Azure China (5) 管理Azure China Powershell
  4. 透析Express.js
  5. Asp.net MVC 中Ajax的使用 [分享]
  6. axis
  7. MVVM架构~knockoutjs系列之验证信息自定义输出~续
  8. js里slice,substr和substring的区别
  9. 正则表达式匹配/data/misc/wifi/wpa_supplicant.conf的WiFi名称与密码
  10. Ecshop :后台添加新功能 菜单及 管理权限 配置