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

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

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

缓冲区

其实构造一个缓冲区非常简单,根据需分本相关大小的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
相关文章
|
6月前
|
缓存 API C语言
文件的缓冲区
文件的缓冲区
69 1
|
6月前
|
存储 C语言
文件缓冲区
文件缓冲区
49 0
|
2月前
|
存储 算法 API
解密缓冲区协议
解密缓冲区协议
26 0
|
2月前
|
API Python
实现缓冲区协议
实现缓冲区协议
24 0
|
6月前
|
存储 缓存 小程序
详细讲解缓冲区
详细讲解缓冲区
|
12月前
|
存储 网络协议 Linux
网络缓冲区
网络缓冲区
65 0
|
存储 缓存 数据处理
缓存与缓冲区的区别
在计算机科学中,缓存(Cache)和缓冲区(Buffer)是两个常见的概念。尽管它们的功能有些相似,但它们在实际应用中具有不同的用途和工作原理。本文将介绍缓存和缓冲区之间的区别。
599 0
|
C语言
理解缓冲区
理解缓冲区
103 0
|
机器学习/深度学习 索引
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(二)
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(二)
133 0
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(二)