网络数据处理缓冲区和缓冲池实现

简介: 在编写网络应用的时候数据缓冲区是应该比较常用的方式,主要用构建一个内存区用于存储发送的数据和接收的数据;为了更好的利用已有数据缓冲区所以构造一个缓冲池来存放相关数据方便不同连接更好地利用缓冲区,节省不停的构造新的缓冲区所带的损耗问题。

在编写网络应用的时候数据缓冲区是应该比较常用的方式,主要用构建一个内存区用于存储发送的数据和接收的数据;为了更好的利用已有数据缓冲区所以构造一个缓冲池来存放相关数据方便不同连接更好地利用缓冲区,节省不停的构造新的缓冲区所带的损耗问题。

缓冲区

其实构造一个缓冲区非常简单,根据需分本相关大小的byte数组即可;既然是用于存放数据那就自然要实现读和写方法,看一下具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public  class  DataBuffer : IDisposable
     {
         public  byte [] Data;
         private  int  mLength;
         private  int  mPostion = 0;
         internal  int  mCount = 0;
         
         public  DataBuffer( byte [] data)
         {
             Data = data;
             mLength = data.Length;
             mPostion = 0;
             mCount = data.Length;
         }
 
         public  DataBuffer( int  length)
         {
             mLength = length;
             Data = new  byte [length];
         }
         public  void  From(Array source, int  index, int  count)
         {
             Array.Copy(source, index, Data, 0, count);
             mPostion = 0;
             mCount = count;
         }
         public  int  Write( byte [] data)
         {
             return  Write(data, 0);
         }
         public  int  Write( byte [] data, int  index)
         {
             int  count = 0;
             if  (mPostion + (data.Length-index) > mLength)
             {
                 count = mLength - mPostion;
             }
             else
             {
                 count = data.Length - index;
             }
             if  (count > 0)
             {
                 Array.Copy(data, index, Data, mPostion, count);
 
                 mPostion += count;
                 mCount += count;
             }
             return  count;
         }
         public  ArraySegment< byte > Read( int  count)
         {
             int  end = count;
             if  (mPostion + count > mCount)
                 end = mCount - mPostion;
            
             ArraySegment< byte > result= new  ArraySegment< byte >(Data, mPostion, end);
             mPostion += end;
             return  result;
         }
         public  void  Seek()
         {
             Seek(0);
         }
         public  void  Seek( int  postion)
         {
             mPostion = 0;
         }
         public  ArraySegment< byte > GetSegment()
         {
             return  new  ArraySegment< byte >(Data, 0, mCount);
         }
         internal  BufferPool Pool
         {
             get ;
             set ;
         }
         public  void  Dispose()
         {
             if  (Pool != null )
             {
                 mPostion = 0;
                 mCount = 0;
                 Pool.Push( this );
             }
         }
     }

 为了方便使用,Buffer实现了IDisposable接口,其作为就是当释放的时候把Buffer放回到Pool里.

Buffer提供了两个方法分别是Write和Read用于写和读数据,由于缓冲区有大小限制,所以在写的时候会返回一个成功写入的数量;而read则返回一个ArraySegment<byte>用于描述其位置。为什么要这样做呢,其实有些情况一个数据成员会被写入到不同的缓冲区,当读出来的时候就会存要在多个缓冲区中获取。

缓冲池

缓冲池用于发放和回收级冲区,实现一个重用的目的。池的实现并不复杂,封装一个简单的队列操作即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
public  class  BufferPool : IDisposable
     {
         private  static  List<BufferPool> mPools = new  List<BufferPool>();
         private  static  int  mIndex = 0;
         public  static  void  Setup( int  pools, int  buffers)
         {
             Setup(pools, buffers, 2048);
         }
         public  static  void  Setup( int  pools, int  buffers, int  bufferlength)
         {
             lock  (mPools)
             {
                 for  ( int  i = 0; i < pools; i++)
                 {
                     mPools.Add( new  BufferPool(buffers, bufferlength));
                 }
             }
         }
         public  static  void  Clean()
         {
             lock  (mPools)
             {
                 foreach  (BufferPool item in  mPools)
                 {
                     item.Dispose();
                 }
                 mPools.Clear();
             }
         }
         public  static  BufferPool GetPool()
         {
             lock  (mPools)
             {
                 if  (mIndex == mPools.Count)
                 {
                     mIndex = 0;
                 }
                 return  mPools[mIndex];
             }
         }
         Queue<DataBuffer> mBuffers;
         private  int  mBufferLength;
         public  BufferPool( int  count, int  bufferlength)
         {
             mBufferLength = bufferlength;
             mBuffers = new  Queue<DataBuffer>(count);
             for  ( int  i = 0; i < count; i++)
             {
                 mBuffers.Enqueue(createBuffer(bufferlength));
             }
         }
         private  DataBuffer createBuffer( int  length)
         {
             DataBuffer item = new  DataBuffer(length);
             item.Pool = this ;
             return  item;
         }
         public  DataBuffer Pop()
         {
             lock  (mBuffers)
             {
                 return  mBuffers.Count > 0 ? mBuffers.Dequeue() : createBuffer(mBufferLength);
             }
         }
         public  void  Push(DataBuffer buffer)
         {
             lock  (mBuffers)
             {
                 mBuffers.Enqueue(buffer);
             }
         }
         private  bool  mDisposed = false ;
         private  void  OnDispose()
         {
             lock  (mBuffers)
             {
                 while  (mBuffers.Count > 0)
                 {
                     mBuffers.Dequeue().Pool = null ;
                 }
             }
         }
         public  void  Dispose()
         {
             lock  ( this )
             {
                 if  (!mDisposed)
                 {
                     OnDispose();
                     mDisposed = true ;
                 }
             }
         }
     }

BufferPool实现了几个静态方法

Setup

主要目的是用于构造多个缓冲池,缓冲区数量和缓冲区大小。为什么会考虑多个池呢,主要原因是在高并发的来分配处理减低池的负载。

Clean

        用于清除释放缓冲池

GetPool

平均地分发缓冲池给使用者

    一个简单的数据缓冲区和数据缓冲池已经实现了,在后面的文章里会讲述如何构造BufferWriter和BufferReader,根据对象的需要把信息分别写入多个缓冲区和在多个缓冲区中读取信息还原对象。

c#组件设计交流群:47164588 
c# socket :136485198  微博http://weibo.com/ikende
目录
相关文章
|
Dubbo 应用服务中间件
错误:找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain
本文主要讲解如何解决Zookeeper启动时出现错误:找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain 的解决方案
2840 0
错误:找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain
|
监控 安全 C#
attempt to write a readonly database错误的解决(C#,SQLite)
今天打包WPF程序,安装后总是打不开,查看监控日志原来是SQLite的问题,报错如图     当向SQLite数据库中存入新纪录时总是显示attempt to write a readonly a database。
3550 0
ly~
|
12月前
|
Ubuntu Linux C语言
SDL 图形库安装常见错误及解决方法
SDL(Simple DirectMedia Layer)图形库安装过程中可能会遇到编译错误、运行时错误、依赖库缺失等问题。本文总结了在 Linux 和 Windows 系统上常见的错误及解决方法,包括检查和安装依赖库、配置 SDL 子系统、处理 X11 错误等,帮助用户顺利完成 SDL 的安装和配置。
ly~
2099 8
|
数据采集 监控 数据挖掘
ERP系统中的数据分析与报表生成
【7月更文挑战第25天】 ERP系统中的数据分析与报表生成
918 2
|
IDE NoSQL 数据可视化
【Linux】顶级编辑器Vim的基本使用及配置
【Linux】顶级编辑器Vim的基本使用及配置
680 0
【Linux】顶级编辑器Vim的基本使用及配置
|
开发框架 算法 .NET
【工作中问题解决实践 五】DotTrace性能调优最佳实践
【工作中问题解决实践 五】DotTrace性能调优最佳实践
498 0
|
计算机视觉
OpenCV 读写图像、读写像素、修改像素值(案例:图像反处理)
OpenCV 读写图像、读写像素、修改像素值(案例:图像反处理)
760 0
OpenCV 读写图像、读写像素、修改像素值(案例:图像反处理)
|
SQL 关系型数据库 MySQL
MySQL关于日期为零值的处理
前面文章我们介绍过日期和时间字段的查询方法,最近遇到日期值为零的问题。原来了解过和 sql_mode 参数设置有关,但还不是特别清楚,本篇文章将探究下MySQL怎么处理日期值为零的问题。
933 0
|
分布式计算 API Spark