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; | 
Partager