使用方法:将缓存中数据转换成字符串并且进行了加密,然后将加密后的字符串通过SOCKET通信传输,接收方收到后,将字符串解密并且还原出数据。
可单独用于结构体的序列也可用于结构体序列+有规则字符串的序列,看似简单,其实万能而通用,有许多游戏都是这么传数据的,无非是改一改加密和解密的算法罢了。
unit EDcode;
//编码/解码函数库{$WARNINGS OFF}interfaceuses
Windows, 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
var
EncBuf, 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;begintry 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;exceptend;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; finalizationbegin FreeMem (EncBuf, BUFFERSIZE + 100); FreeMem (TempBuf, 2048); DeleteCriticalSection(CSEncode);end; end.