Einzelnen Beitrag anzeigen

Benutzerbild von DataCool
DataCool

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

Indy -IdTcpServer führt zu 100% CPU -Last

  Alt 19. Nov 2003, 00:49
Hi Leute,

ich bin's mal wieder mit einer Indy-Frage, ich kämpfe jetzt schon sehr lange mit den Indy-Komponenten, aber manchmal könnte ich das Blocking Sockets verfluchen. Warum haben die sich dafür entschieden ?

Aufgabe:
Bildübertragung eines Webcam-Bilds so gut und schnell wie möglich.

Problem:
Im Moment verwende ich produktiv gerade ein eigenes Protokoll das noch sehr viel Overhead hat.
Aber 4 Leute können problemlos mein Bild betrachten.
Jetzt habe ich mein Protokoll wirklich auf das wichtigste beschränkt die Bildübertragung.

Code Beispiel Server :
Code:
Var ms  : TMemoryStream;
      ImgWrapper : TImageWrapper;
      sCmd : String;
begin
   // Speicher zur Bildablage im Stream erzeugen
   ms := TMemoryStream.Create;
   // KLasse zum Abgreifen des Video-Bild erzeugen
   imgWrapper := TImageWrapper.Create(AThread,frmMain.Video);
   try
      imgWrapper.FileSys := bFileSys;
      imgWrapper.Kompression := Einstell.Compression; // Bildkompression setzen
      // Solange eine Socket-Verbindung besteht jetzt das Bild zum Kunden übertragen
      While (AThread.Connection.Connected) do begin
         // MemoryStream leeren
         ms.clear;
         // aktuelles Bild jetzt laden/abgreifen
         if imgWrapper.loadImage then begin
            // Geladenes Bild in Strean schreiben
            imgWrapper.WriteToStream(ms);
            // Bildspeicherposition auf den Anfang setzen
            ms.Position := 0;
            // Bild einfach in den Buffer schreiben und abschicken
            // durch die entsprechenden Parameter in WriteStream,
            // steht in den ersten vier Bytes des Streams die Stream Grösse
            try
               AThread.Connection.OpenWriteBuffer;
               AThread.Connection.WriteStream(ms,true,true);
               AThread.Connection.CloseWriteBuffer;
            except
               logf.log('Versuche Write Buffer zu canceln',1);
               //AThread.Connection.CancelWriteBuffer;
               AThread.Connection.ClearWriteBuffer;
               //AThread.Connection.DisconnectSocket;
            end;
         end
         else begin
            // es konnte kein Bild geladen werden, es wird jetzt der leere Stream zum Client geschickt
            // der überprüft anhand der Streamgrösse ob er darauf reagiert, so wird der normale
            // Befehlsablauf nicht unterbrochen
            AThread.Connection.OpenWriteBuffer;
            try
               AThread.Connection.WriteStream(ms,true,true);
               AThread.Connection.CloseWriteBuffer;
            except
               //AThread.Connection.CancelWriteBuffer;
               AThread.Connection.ClearWriteBuffer;
            end;
            logf.log('Send empty stream size 0',1);
         end;
      end;
   finally
      // Speicher wieder freigeben
      ms.Clear;
      FreeAndNil(ms);
      FreeAndNil(ImgWrapper);
   end;
Code Bsp. Client :
Code:
// die Procedure StreamNow wird innerhalb des VideoStreamThread immer wieder aufgerufen
procedure TVideoStreamThread.StreamNow;
begin
   // Speicher leeren
   ms.Clear; //     
   try
      if (TcpCon.Connected) and (not Terminated) then begin
         try
            TcpCon.ReadStream(ms);
         except
            ms.clear;
         end;
         if ms.Size > 0 then begin
            // Stream Position auf null, damit vom Anfang gelesen wird
            ms.Position := 0;
            jpg.LoadFromStream(ms);
            // Haben wir ein gültiges Jpg
            if not jpg.Empty then begin
               aktJpg := jpg;
               // Jpg zeichnen
               Synchronize(PaintImage);
            end;
         end;
      end;
   finally
      // Memory-Stream leeren
      ms.clear;
   end;
end;
Wie Ihr seht beschränkte ich mich jetzt auf die reine Bildübertragung, das Problem dabei ist, das das Bild zwar super schnell und super flüssig wird, aber ab dem dritten User beim Server die CPU Last auf 100% steigt und ich nicht nachvollziehen kann warum.
In meinen Logfile steht kein einziger Fehler von irgenteinem Thread, kann es sein das diese intensiven Threads für Windows bzw. Indy zuviel sind ?

Jeder Kommentar hilft vielleicht weiter, sitze schon etwas länger darüber und komme jetzt gerade nicht weiter.
Und das ist echt frustierend bin schon am überlegen, ob ich das ganze Projekt auf die ICS-Komponenten umschreibe, aber das würde etwas dauern und ich habe mit denen auch noch keinerlei Erfahrung.

Was sagt Ihr ?

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