//代码修改于 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;