Einzelnen Beitrag anzeigen

Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Indy 10 tcp client server demo

  Alt 25. Apr 2012, 11:03
Hi Bernhard,

habe mir gerade nur den Code im Server angeschaut und da sind mir
auf Anhieb ein paar Probleme aufgefallen:
- Im OnExecute des IndyServers muss der komplette Code Thread-Safe sein,
weil er innerhalb des Conntext eines Threads abläuft, das bedeutet sämtliche
VCL-Gui Zugriffe müssen Thread-Safe sein:
Memo1.lines.add('blaBla'); Geht so nicht. Auch der Zugriff auf gemeinsame Ressourcen muss geschützt sein,
Delphi-Quellcode:
  public
    { Public-Deklarationen }

    abmp: TBitMap; // <---- nicht Thread-Safe

    aMyRecordIndy: TMyThreadSafeRecord;
    // ^^ hört sich Thread Safe ein, aber wenn 2 Clients gleichzeitig connecten
    // und den Record benutzen, was passiert dann ?
BEnutzung des Bmps:
Delphi-Quellcode:
    3:
      begin
        ///
        Memo1.Lines.Add('record received AND JOB done!');

        abmp.Height := 300;
        abmp.Width := 300;

        DrawRandomBitMap(abmp);

        ServerImage.Picture.Bitmap.Assign(abmp);
// Jeder Client braucht sein eigenes Bmp !!

Des Weiteren habe ich im SVN nicht die Units gefunden:
Unit_Indy_Functions, Unit_Indy_Classes;

Wenn die Function SendStream dort noch wie in den anderen Threads von Dir so existiert,
das
Delphi-Quellcode:
  result := false;
  try
    // sende ...
    // ...
  finally
    // ...
  end;
  result := true; // wird immer gesetzt, egal ob ein Fehler auftritt oder nicht
Des Weiteren solltest Du solche Boolean Vergleiche lassen:
Delphi-Quellcode:
  if (SendBuffer(AContext, LBuffer) = False) then // falsch, gibts genug Threads zu dem Thema

  // richtig:
  if not (SendBuffer(AContext, LBuffer)) then ...
Einen letzten Tipp habe ich für Dich noch; Ich würde(so mache ich es meistens auf jeden Fall)
eine Klasse TMyClient definieren diese pro Connection wie folgt verwenden:
Delphi-Quellcode:
// Im OnConnect
  AContext.Data := TMyClient.Create;

// Im OnDisConnect:
  If Assigned(AContext.Data) then
  begin
    if AContext.Data is TMyClient then
      TMyClient(AContext.Data).Free;
    AContext.Data := nil; // auf jeden Fall auf nil setzen, sonst versucht Indy das ganze freizugeben
  end;

// Im OnExecute
var myClient : TMyClient;
begin
  // ....
  try
    myClient := TMyClient(AContext.Data);
  except
    myClient := nil;
  end;

  if Assigned(myClient) then
  begin
    // je nach Definition des TMyClients Object hast Du jetzt geschützte Ressouren pro Client
    // also Daten/Infos darein oder als lokale Var im OnExecute des Servers

  end;

  // ...
Hoffe das bringt Dich ein wenig weiter,

Greetz Data
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat