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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
procedure TServiceCom.doRead(tp, id: integer; Socket: TCustomWinSocket);
var
bufferLu : PChar ; // buffer contenant le message lu
sizeLue : integer; // taille effectivement lue
bufferMemo : PChar; // buffer mémorisé au tour précédent si débordement
sizeMemo : integer; // taille de ce buffer mémorisé
bufferTot : PChar; // concaténation de bufferLu et bufferMemo
sizeTot : integer; // taille totale des datas à traiter
ptrBuffer : PChar; // pointeur qui parcourt le bufferTot
size : integer; // taille attendue du message courant
cumul : integer; // cumul tailles messages traités
debordement : boolean; // indique si le message en cours est incomplet
traducDone : boolean; // passage de index lstSck à Ident : le faire une seule
// fois quand boucle sur plusieurs messages !
function LireBuf(var sz: integer) : PChar;
var
szlue : integer;
p1,p2 : PChar ;
begin
sz := socket.ReceiveLength;
p1 := PChar(GAlloc(sz));
szlue := Socket.ReceiveBuf(p1^, sz);
if szlue > 0 then begin
if szlue < sz then begin
p2 := PChar(GAlloc(szlue));
move(p1^,p2^,szlue);
GFree(p1);
sz := szlue;
result := p2;
end else
result := p1;
end else begin
GFree(p1);
sz := 0;
result := nil;
end;
end;
procedure Concatener(p1: PChar; l1: integer;
p2: PChar; l2: integer;
out px: PChar; out lx: integer);
begin
px := PChar(GAlloc(l1+l2));
move(p1^, px^ ,l1);
move(p2^,(px+l1)^,l2);
lx := l1+l2;
try GFree(p1); finally end;
try GFree(p2); finally end;
end;
procedure traiterMessage(msg: Pchar; siz: integer);
// id est l'identifiant de socket client
// par convention, le client m'envoie une première chaine d'identification
// juste apres l'ouverture de socket
// ça me permet d'avoir plusieurs clients sur la même machine
var
buf : PChar;
begin
if id<0 then begin // premier read coté serveur
getmem(buf,siz+1);
move(msg^, buf^, siz);
buf[siz]:=#0;
// on update id pour le cas où 2ème msg arrivé en même temps
id := connectSocket(socket, tp, string(buf));
freemem(buf);
end
else begin
// attention, on passe plusieurs fois ici si plusieurs messages ...
if not traducDone then begin
id := Index2Ident(tp, id);
traducDone := true;
end;
if (id>=0) then begin
buf := PChar(GAlloc(siz));
move(msg^, buf^, siz);
// ICI, traitement applicatiff du message reçu 'buf'
end
else
Log('DoRead type inconnu:'+IntToStr(tp)+' ignoré');
end;
end;
begin
// lecture dans la socket (en sortie, sizeLue = taille rééllement obtenue)
bufferLu := LireBuf(sizeLue);
if sizeLue > 0 then begin
// récupération d'un éventuel message incomplet du tour précédent
if Socket.Data = nil then begin
bufferTot := bufferLu;
sizeTot := sizeLue;
end else begin
bufferMemo := socket.Data;
sizeMemo := GSize(HGlobal(bufferMemo));
Socket.Data := nil;
Concatener(bufferMemo, sizeMemo,
bufferLu , sizeLue ,
bufferTot , sizeTot );
end;
// analyse du buffer : découpage en messages
// chaque message émis est précédé d'un integer indiquant sa taille
ptrBuffer := bufferTot;
cumul := 0;
size := 0;
traducDone:= false;
while cumul < sizeTot do begin
// taille du message à recevoir
if (sizeTot-cumul) >= sizeof(integer) then begin
size := (Pinteger(ptrBuffer))^;
debordement := (cumul+size) > sizeTot;
end else
debordement := true;
// si dernier message incomplet, le mémoriser
if debordement then begin
sizeMemo := sizeTot - cumul;
bufferMemo := PChar(GAlloc(sizeMemo));
move(ptrBuffer^,bufferMemo^,sizeMemo);
Socket.Data := bufferMemo;
cumul := sizeTot;
// sinon le traiter
end else begin
if (size>sizeof(integer)) then // si = , c'est le polling client
traiterMessage(PChar(ptrBuffer+sizeof(integer)),
size-sizeof(integer));
ptrBuffer := ptrBuffer + size;
cumul := cumul + size;
end;
end; // while cumul < sizeTot
try GFree(bufferTot); finally end;
end; // if sizeLue>0
end; |