使用方法:将缓存中数据转换成字符串并且进行了加密,然后将加密后的字符串通过SOCKET通信传输,接收方收到后,将字符串解密并且还原出数据。
可单独用于结构体的序列也可用于结构体序列+有规则字符串的序列,看似简单,其实万能而通用,有许多游戏都是这么传数据的,无非是改一改加密和解密的算法罢了。
unit EDcode;
//编码/解码函数库
{$WARNINGS OFF}
interface
usesWindows, SysUtils, Classes;
const
BUFFERSIZE=32768;
DEFBLOCKSIZE=24;
HEADCHAR = '#';TAILCHAR = '!';
const
CM_TEST = 1000;
CM_TEST2 = 1001;
const
SM_TEST = 9000;
SM_TEST2 = 9001;
type
TDefaultMessage=packed record //Size=18
MsgID: word;
Param1: Integer;
Param2: integer;
Param3: integer;
Param4: Integer;
end;
function EncodeMessage (smsg: TDefaultMessage): AnsiString;
function DecodeMessage (str: AnsiString): TDefaultMessage;
function EncodeString (str: AnsiString): AnsiString;
function DecodeString (str: AnsiString): AnsiString;
function EncodeBuffer (buf: PAnsiChar; bufsize: integer): AnsiString;
procedure DecodeBuffer (src: AnsiString; buf: PAnsiChar; bufsize: integer);
function MakeDefaultMsg (msgid:word; param1,param2,param3,param4:integer):TDefaultMessage;
var
CSEncode: TRTLCriticalSection;
implementation
varEncBuf, TempBuf: PAnsiChar;
function MakeDefaultMsg (msgid:word; param1,param2,param3,param4:integer):TDefaultMessage;
begin
result.MsgID := msgid;
result.Param1 := param1;
result.Param2 := param2;
result.Param3 := param3;
result.Param4 := param4;
end;
procedure Encode6BitBuf (src, dest: PAnsiChar; srclen, destlen: integer);
var
i, restcount, destpos: integer;
made, ch, rest: byte;
begin
try
restcount := 0;
rest := 0;
destpos := 0;
for i:=0 to srclen - 1 do begin
if destpos >= destlen then break;
ch := byte (src[i]);
made := byte ((rest or (ch shr (2+restcount))) and $3F);
rest := byte (((ch shl (8 - (2+restcount))) shr 2) and $3F);
Inc (restcount, 2);
if restcount < 6 then begin
dest[destpos] := AnsiChar(made + $3C);
Inc (destpos);
end else begin
if destpos < destlen-1 then begin
dest[destpos] := AnsiChar(made + $3C);
dest[destpos+1] := AnsiChar(rest + $3C);
Inc (destpos, 2);
end else begin
dest[destpos] := AnsiChar(made + $3C);
Inc (destpos);
end;
restcount := 0;
rest := 0;
end;
end;
if restcount > 0 then begin
dest[destpos] := AnsiChar (rest + $3C);
Inc (destpos);
end;
dest[destpos] := #0;
except
end;
end;
procedure Decode6BitBuf (source: AnsiString; buf: PAnsiChar; buflen: integer);
const
Masks: array[2..6] of byte = ($FC, $F8, $F0, $E0, $C0);
var
i, len, bitpos, madebit, bufpos: integer;
ch, tmp, _byte: Byte;
begin
try
len := Length (source);
bitpos := 2;
madebit := 0;
bufpos := 0;
tmp := 0;
for i:=1 to len do begin
if Integer(source[i]) - $3C >= 0 then
ch := Byte(source[i]) - $3C
else begin
bufpos := 0;
break;
end;
if bufpos >= buflen then break;
if (madebit+6) >= 8 then begin
_byte := Byte(tmp or ((ch and $3F) shr (6-bitpos)));
buf[bufpos] := AnsiChar(_byte);
Inc (bufpos);
madebit := 0;
if bitpos < 6 then Inc (bitpos, 2)
else begin
bitpos := 2;
continue;
end;
end;
tmp := Byte (Byte(ch shl bitpos) and Masks[bitpos]);
Inc (madebit, 8-bitpos);
end;
buf [bufpos] := #0;
except
end;
end;
function DecodeMessage (str: AnsiString): TDefaultMessage;
var
msg: TDefaultMessage;
begin
try
EnterCriticalSection (CSencode);
Decode6BitBuf (str, EncBuf, 1024);
Move (EncBuf^, msg, sizeof(TDefaultMessage));
Result := msg;
finally
LeaveCriticalSection (CSencode);
end;
end;
function DecodeString (str: AnsiString): AnsiString;
begin
try
EnterCriticalSection (CSencode);
Decode6BitBuf (str, EncBuf, BUFFERSIZE);
Result := StrPas (EncBuf);
finally
LeaveCriticalSection (CSencode);
end;
end;
procedure DecodeBuffer (src: AnsiString; buf: PAnsiChar; bufsize: integer);
begin
try
EnterCriticalSection (CSencode);
Decode6BitBuf (src, EncBuf, BUFFERSIZE);
Move (EncBuf^, buf^, bufsize);
finally
LeaveCriticalSection (CSencode);
end;
end;
function EncodeMessage (smsg: TDefaultMessage): AnsiString;
begin
try
EnterCriticalSection (CSencode);
Move (smsg, TempBuf^, sizeof(TDefaultMessage));
Encode6BitBuf (TempBuf, EncBuf, sizeof(TDefaultMessage), 1024);
Result := StrPas (EncBuf);
finally
LeaveCriticalSection (CSencode);
end;
end;
function EncodeString (str: AnsiString): AnsiString;
begin
try
EnterCriticalSection (CSencode);
Encode6BitBuf (PAnsiChar(str), EncBuf, Length(str), BUFFERSIZE);
Result := StrPas (EncBuf);
finally
LeaveCriticalSection (CSencode);
end;
end;
function EncodeBuffer (buf: PAnsiChar; bufsize: integer): AnsiString;
begin
try
EnterCriticalSection (CSencode);
if bufsize < BUFFERSIZE then begin
Move (buf^, TempBuf^, bufsize);
Encode6BitBuf (TempBuf, EncBuf, bufsize, BUFFERSIZE);
Result := StrPas (EncBuf);
end else
Result := '';
finally
LeaveCriticalSection (CSencode);
end;
end;
initialization
begin
GetMem (EncBuf, BUFFERSIZE + 100);
GetMem (TempBuf, 2048);
InitializeCriticalSection(CSEncode);
end;
finalization
begin
FreeMem (EncBuf, BUFFERSIZE + 100);
FreeMem (TempBuf, 2048);
DeleteCriticalSection(CSEncode);
end;
end.