用于拼包和解码的环形缓冲区类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test
{
    /// <summary>
    /// 环形缓冲区
    /// </summary>
    public class CRawBuffer
    {
        byte[] m_BufArr;
        int m_i4BufLen;   //数据缓冲区大小
        public int m_i4ReadPos;   //读游标
        public int m_i4WritePos;  //写游标

const int const_maxLen = 102400;

public CRawBuffer(int i4MaxQueueBufferSize)
        {
            m_BufArr = new byte[i4MaxQueueBufferSize];
            if (i4MaxQueueBufferSize <= 0 || i4MaxQueueBufferSize > const_maxLen)
            {
                m_BufArr = new byte[const_maxLen];
                m_i4BufLen = const_maxLen;
            }
            else
            {
                m_BufArr = new byte[i4MaxQueueBufferSize];
                m_i4BufLen = i4MaxQueueBufferSize;
            }
            //m_BufArr.SetValue(0, 0, m_BufArr.Length - 1);
            m_i4ReadPos = 0;
            m_i4WritePos = 0;
        }

public void SetRawDataToBuffer(byte[] byteArr, int nDataLen)
        {
            for (int i = 0; i < nDataLen; i++)
            {
                //接收的数据量达到缓冲区最大值,则将m_i4WritePos置0,从头开始计数(循环计数)
                if (m_i4WritePos == m_i4BufLen)
                {
                    m_i4WritePos = 0;
                }
                m_BufArr[m_i4WritePos] = byteArr[i];
                m_i4WritePos++;//更新要写入数据位置

//接收的数据量达到缓冲区最大值,则将m_i4WritePos置0,从头开始计数(循环计数)
                if (m_i4WritePos == m_i4BufLen)
                {
                    m_i4WritePos = 0;
                }
            }
        }

public void SetUsedLength(int i4Length)
        {
            //根据已经使用数据个数,移动开始标记指针
            m_i4ReadPos = m_i4ReadPos + i4Length;
            if (m_i4ReadPos >= m_i4BufLen)
                m_i4ReadPos = m_i4ReadPos - m_i4BufLen;
        }

public int GetData(byte[] byteArr, int i4Length)
        {
            int i4RealLength = 0;
            int i4ReadPosEnd = m_i4WritePos;//固定数据末尾位置
            if (i4ReadPosEnd > m_i4ReadPos)//正常情况,读数据的最新位置大于上次读完数据的位置,取出数据
            {
                i4RealLength = i4ReadPosEnd - m_i4ReadPos;//实际数据长度
                if (i4RealLength >= i4Length)//实际数据长,要求获取数据短,这样就只给需要的长度数据
                {

memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, i4Length);
                    i4RealLength = i4Length;
                }
                else//要求获取数据比实际数据长
                {
                    memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, i4RealLength);
                }
            }
            else if (i4ReadPosEnd < m_i4ReadPos)//越界情况,读数据的最新位置小于上次读完数据的位置,分两次拷贝数据                                         
            {
                //检查缓冲区末尾长度是否够用m_i4BufLen
                if (m_i4BufLen - m_i4ReadPos >= i4Length)//尾段够用
                {
                    memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, i4Length);
                    i4RealLength = i4Length;
                }
                else//必须跨段两次写入
                {
                    //先读完缓冲区,再从缓冲区头部开始读数
                    memcpy(byteArr, 0, m_BufArr, m_i4ReadPos, m_i4BufLen - m_i4ReadPos);
                    i4RealLength = m_i4BufLen - m_i4ReadPos + i4ReadPosEnd;//实际数据长度
                    if (i4RealLength >= i4Length)//两段长度之和大于i4Length
                    {
                        memcpy(byteArr, m_i4BufLen - m_i4ReadPos, m_BufArr, 0, i4Length - (m_i4BufLen - m_i4ReadPos));
                        i4RealLength = i4Length;
                    }
                    else//两段长度之和小于i4Length
                    {
                        memcpy(byteArr, m_i4BufLen - m_i4ReadPos, m_BufArr, 0, i4ReadPosEnd);
                    }
                }
            }
            else return 0;//i4ReadPosEnd 和 m_i4ReadPos 重叠

return i4RealLength;
        }

private void memcpy(byte[] targetArr, int nTargetOffset, byte[] sourceArr, int nSourceOffset, int nDataLen)
        {
            for (int i = 0; i < nDataLen; i++)
            {
                targetArr[i + nTargetOffset] = sourceArr[i + nSourceOffset];
            }
        }
    }
}

时间: 2024-11-01 13:32:15

用于拼包和解码的环形缓冲区类的相关文章

【转】环形缓冲区

原文地址:http://blog.csdn.net/linlinlinxi007/article/details/5086806 在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据.环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问. 1.环形缓冲区的实现原理 环形缓冲区通常有一个读指针和一个写指针.读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区.通过移动读指针和写指针就可以实现缓冲区的数据读取和写人.在通常情况下,环形缓冲区的

生产者消费者模式下的并发无锁环形缓冲区

上一篇记录了几种环形缓冲区的设计方法和环形缓冲区在生产者消费者模式下的使用(并发有锁),这一篇主要看看怎么实现并发无锁. 0.简单的说明 首先对环形缓冲区做下说明: 环形缓冲区使用改进的数组版本,缓冲区容量为2的幂 缓冲区满阻塞生产者,消费者进行消费后,缓冲区又有可用资源,由消费者唤醒生产者 缓冲区空阻塞消费者,生产者进程生产后,缓冲区又有可用资源,由生产者唤醒消费者 然后对涉及到的几个技术做下说明: ⑴CAS,Compare & Set,X86下对应的是CMPXCHG 汇编指令,原子操作,基本

使用无锁队列(环形缓冲区)注意事项

环形缓冲区是生产者和消费者模型中常用的数据结构.生产者将数据放入数组的尾端,而消费者从数组的另一端移走数据,当达到数组的尾部时,生产者绕回到数组的头部.如果只有一个生产者和一个消费者,那么就可以做到免锁访问环形缓冲区(Ring Buffer).写入索引只允许生产者访问并修改,只要写入者在更新索引之前将新的值保存到缓冲区中,则读者将始终看到一致的数据结构.同理,读取索引也只允许消费者访问并修改. 环形缓冲区实现原理图 如图所示,当读者和写者指针相等时,表明缓冲区是空的,而只要写入指针在读取指针后面

[转]环形缓冲区

在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据.环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问. 1.环形缓冲区的实现原理 环形缓冲区通常有一个读指针和一个写指针.读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区.通过移动读指针和写指针就可以实现缓冲区的数据读取和写入.在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针.如果仅仅有一个读用户和一个写用户,那么不需要添加互斥保护机制就可以保证数据的正确

SQL Server 环形缓冲区(Ring Buffer) -- SQL Server 与Ring Buffer的关系介绍

SQL Server 环形缓冲区(Ring Buffer) -- SQL Server 与Ring Buffer的关系 SQL Server 操作系统(SQLOS)负责管理特定于SQL Server的操作系统资源.其中相关的动态管理试图sys.dm_os_ring_buffers将被标识为仅供参考.不提供支持.不保证以后的兼容性. 先看看记录的不同的Ring Buffer类型. select distinct ring_buffer_type from sys.dm_os_ring_buffer

SQL Server 环形缓冲区(Ring Buffer) -- 环形缓冲在AlwaysOn的应用

SQL Server 环形缓冲区(Ring Buffer) -- 环形缓冲在AlwaysOn的应用 可以从SQL Server环形缓冲区得到一些诊断AlwaysOn的信息,或从sys.dm_os_ring_buffers动态管理视图.环形缓冲在SQL Server启动的时候创建,在SQL Server系统内记录告警用于内部诊断.它们不被支持,但你仍能从中获取有用的信息.下面的查询能从AlwaysON环形缓冲获取所有的事件记录. SELECT * FROM sys.dm_os_ring_buffe

C语言创建循环缓冲区(环形缓冲区)-- Circular Buffer(Ring Buffer)

由于嵌入式系统的资源有限性,循环缓冲区数据结构体(Circular Buffer Data Structures)被大量的使用. 循环缓冲区(也称为环形缓冲区)是固定大小的缓冲区,工作原理就像内存是连续的且可循环的一样.在生成和使用内存时,不需将原来的数据全部重新清理掉,只要调整head/tail 指针即可.当添加数据时,head 指针前进.当使用数据时,tail 指针向前移动.当到达缓冲区的尾部时,指针又回到缓冲区的起始位置. 目录: 为什么使用循环缓冲区 C 实例 使用封装 API设计 确认

环形缓冲区

作者:曾志优 出处:http://www.cnblogs.com/zengzy 1.环形缓冲区 缓冲区的好处,就是空间换时间和协调快慢线程.缓冲区可以用很多设计法,这里说一下环形缓冲区的几种设计方案,可以看成是几种环形缓冲区的模式.设 计环形缓冲区涉及到几个点,一是超出缓冲区大小的的索引如何处理,二是如何表示缓冲区满和缓冲区空,三是如何入队.出队,四是缓冲区中数据长度如何计算. ps.规定以下所有方案,在缓冲区满时不可再写入数据,缓冲区空时不能读数据 1.1.常规数组环形缓冲区 设缓冲区大小为N

环形缓冲区的设计及其在生产者消费者模式下的使用(并发有锁环形队列)

1.环形缓冲区 缓冲区的好处,就是空间换时间和协调快慢线程.缓冲区可以用很多设计法,这里说一下环形缓冲区的几种设计方案,可以看成是几种环形缓冲区的模式.设计环形缓冲区涉及到几个点,一是超出缓冲区大小的的索引如何处理,二是如何表示缓冲区满和缓冲区空,三是如何入队.出队,四是缓冲区中数据长度如何计算. ps.规定以下所有方案,在缓冲区满时不可再写入数据,缓冲区空时不能读数据 1.1.常规数组环形缓冲区 设缓冲区大小为N,队头out,队尾in,out.in均是下标表示: 初始时,in=out=0 队头