简单的缓冲区助手类

//代码修改于 ICS 网络通信控件 中的TBuff类
 
    在某些有性能要求的地方,我们会开辟一块缓冲区,也就是分配一块内存,数据在都在此内存中操作,避免频繁的内存分配释放操作。
尤其在写服务器端程序时,这点显得非常重要,如果是普通的客户端程序,本文所说的方法,就不要考虑了,毕竟是操作有些繁琐。
这个助手类的目的是提高性能,同时还有个特点,助手类内部会进行内存边界的检测,保证在往缓冲区内写数据的时候,不会发生溢出,
听过说 著名的“缓冲区溢出”攻击吧。另外一个特点是,缓冲区的大小是在创建的时候,一次分配好,而不能进行修改。目的是配合内存
池使用,减少内存碎片的产生。但类的内部提供了,动态改变缓冲区大小的功能。只不过在这里被屏蔽掉了。要恢复此功能,很简单
修改代码如下: 
 
  1 unit WSockBuf;
  2 interface
  3 uses
  4   SysUtils;
  5 type
  6   TFixedBuffer = class
  7   private
  8     FBuf      : Pointer;
  9     FBufSize  : Integer;
 10     FWrCount  : Integer;
 11     FRdCount  : Integer;
 12     procedure   SetBufSize(newSize : Integer);
 13    // function    Remove(Len : Integer) : Integer;
 14     function    Peek(var Len : Integer) : Pointer;
 15   public
 16     procedure   Clear();
 17     constructor Create(nSize : Integer=4096); virtual;
 18     destructor  Destroy; override;
 19     function    Write(Data : Pointer; Len : Integer) : Integer;
 20     function    WriteStr(const Data:string):Integer;
 21     function    Read(Data : Pointer; Len : Integer) : Integer;
 22     function    ReadStr(Len:Integer=0):string; //Len <=0,读取全部数据
 23   public
 24     property    Buf:Pointer read FBuf;
 25     property    Position:Integer read FWrCount;
 26     property    BufSize : Integer read FBufSize;// write SetBufSize;
 27   end;
 28 implementation
 29 
 30 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
 31 constructor TFixedBuffer.Create(nSize : Integer);
 32 begin
 33   inherited Create;
 34   FWrCount  := 0;
 35   FRdCount  := 0;
 36   SetBufSize(nSize);
 37 end;
 38 
 39 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
 40 destructor TFixedBuffer.Destroy;
 41 begin
 42     if Assigned(Buf) then
 43         FreeMem(Buf, FBufSize);
 44     inherited Destroy;
 45 end;
 46 
 47 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
 48 procedure TFixedBuffer.SetBufSize(newSize : Integer);
 49 var
 50     newBuf : Pointer;
 51 begin
 52     if newSize <= 0 then
 53         newSize := 1514;
 54     if newSize = FBufSize then
 55         Exit;
 56     if FWrCount = FRdCount then begin
 57         { Buffer is empty }
 58         if Assigned(Buf) then
 59             FreeMem(Buf, FBufSize);
 60         FBufSize := newSize;
 61         GetMem(FBuf, FBufSize);
 62     end
 63     else begin
 64         { Buffer contains data }
 65         GetMem(newBuf, newSize);
 66         Move(Buf^, newBuf^, FWrCount);
 67         if Assigned(Buf) then
 68             FreeMem(Buf, FBufSize);
 69         FBufSize := newSize;
 70         FBuf      := newBuf;
 71     end;
 72 end;
 73 
 74 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
 75 function TFixedBuffer.Write(Data : Pointer; Len : Integer) : Integer;
 76 var
 77     Remaining : Integer;
 78     Copied    : Integer;
 79 begin
 80     Remaining := FBufSize - FWrCount;
 81     if Remaining <= 0 then
 82         Result := 0
 83     else begin
 84         if Len <= Remaining then
 85             Copied := Len
 86         else
 87             Copied := Remaining;
 88         Move(Data^, (PChar(Buf) + FWrCount)^, Copied);
 89         FWrCount := FWrCount + Copied;
 90         Result  := Copied;
 91     end;
 92 end;
 93 
 94 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
 95 function TFixedBuffer.Read(Data : Pointer; Len : Integer) : Integer;
 96 var
 97     Remaining : Integer;
 98     Copied    : Integer;
 99 begin
100     Remaining := FWrCount - FRdCount;
101     if Remaining <= 0 then
102         Result := 0
103     else begin
104         if Len <= Remaining then
105             Copied := Len
106         else
107             Copied := Remaining;
108         Move((PChar(Buf) + FRdCount)^, Data^, Copied);
109         FRdCount := FRdCount + Copied;
110         if FRdCount = FWrCount then begin
111             FRdCount := 0;
112             FWrCount := 0;
113         end;
114         Result := Copied;
115     end;
116 end;
117 
118 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
119 function TFixedBuffer.Peek(var Len : Integer) : Pointer;
120 var
121     Remaining : Integer;
122 begin
123     Remaining := FWrCount - FRdCount;
124     if Remaining <= 0 then begin
125         Len    := 0;
126         Result := nil;
127     end
128     else begin
129         Len    := Remaining;
130         Result := Pointer(PChar(Buf) + FRdCount);
131     end;
132 end;
133 (*
134 function TFixedBuffer.Remove(Len : Integer) : Integer;
135 var
136     Remaining : Integer;
137     Removed   : Integer;
138 begin
139     Remaining := FWrCount - FRdCount;
140     if Remaining <= 0 then
141         Result := 0
142     else begin
143         if Len < Remaining then
144             Removed := Len
145         else
146             Removed := Remaining;
147         FRdCount := FRdCount + Removed;
148         if FRdCount = FWrCount then begin
149             FRdCount := 0;
150             FWrCount := 0;
151         end;
152         Result := Removed;
153     end;
154 end;
155 *)
156 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
157 function TFixedBuffer.WriteStr(const Data: string): Integer;
158 begin
159   Result := Write(Pointer(Data),Length(Data));
160 end;
161 function TFixedBuffer.ReadStr(Len: Integer): string;
162 begin
163   if Len <= 0 then len := system.MaxLongint;
164   Peek(Len);
165   if Len > 0 then
166   begin
167     SetLength(Result,Len);
168     Read(Pointer(Result),Len);
169   end
170   else Result := '';
171 end;
172 procedure TFixedBuffer.Clear;
173 begin
174   FWrCount  := 0;
175   FRdCount  := 0;
176 end;
原文地址:https://www.cnblogs.com/lwm8246/p/2756253.html