TMemoryStream macht Probleme beim wiederholten Aufruf/Zugriff auf den Stream
-
Hallo,
habe
TMemoryStream *Stream = new TMemoryStream ; //Speicher für Screenshot-Stream erzeugen
global deklariert in einer Anwendung mit einem Serversocket, um einen Stream über Socketverbindung zum Client zu übertragen.
Zunächst sendet der Client ein Zeichen, um den Server zu veranlassen, einen Screenshot vom Bildschirm zu machen. Der Server ruft dazu dann folgende Funktion auf:
void Screenshot() { HDC dc = GetDC(NULL); TJPEGImage *pJPG_Bild = new TJPEGImage(); Graphics::TCanvas *ScreenCanvas = new Graphics::TCanvas(); ScreenCanvas->Handle = dc; Stream->Clear(); //evtl. alten Inhalt des Streams löschen Form1->Screenshot->AutoSize = true; Form1->Screenshot->Center = true; Form1->Screenshot->Top = 0; Form1->Screenshot->Left = 0; Form1->Screenshot->Picture->Bitmap->Width = Screen->Width; Form1->Screenshot->Picture->Bitmap->Height= Screen->Height; TRect rect = Rect(0,0,Screen->Width, Screen->Height); //Screenshot ist hier ein Bitmap (noch kein jpg!) Form1->Screenshot->Picture->Bitmap->Canvas->CopyRect(rect, ScreenCanvas, rect); ReleaseDC(NULL,dc); delete ScreenCanvas; //Objekt löschen und Speicher wieder frei geben //aus Screenshot->Picture ein jpg-Bild erzeugen zum späteren versenden: pJPG_Bild->Assign(Form1->Screenshot->Picture->Bitmap); pJPG_Bild->CompressionQuality = 50; //jpg-Bild in Stream zur Übertragung kopieren: Form1->Label1->Caption="Bild vor in Stream schreiben"; pJPG_Bild->SaveToStream(Stream); delete pJPG_Bild; //Objekt löschen und Speicher wieder frei geben Stream->Position=0; //zum Anfang des Datenstreams gehen //Streamgröße (Datenmenge) zuerst übermitteln, damit Empfänger weiß, wann Übertragung zu Ende ist: Service1->ServerSocket1->Socket->Connections[0]->SendText(IntToStr(Stream->Size)); //auf Bestätigung des Client nun warten, damit Stream gesendet werden kann }
Daraufhin empfängt der Client die Bildgröße u. quittiert dies mit einem Zeichen an den Server.
Der Server reagiert wie folgt:Stream->Position=0; Service1->ServerSocket1->Socket->Connections[0]->SendStream(Stream); //Stream senden
Der Client empfängt den Stream korrekt u. hat so das Bild erhalten, was er wieder mit einem Zeichen an den Server quittiert und die Socketverbindung unterbricht.
Der Server reagiert so:Stream->Clear(); //Stream löschen und damit wieder Speicher freigeben
Dies funktioniert einwandfrei, aber nur einmal!!
Wiederhole ich die Geschichte, dann bleibt der Server bei der ersten Anweisung, die auf den Stream zugreift (das ist hier "Stream->Clear();" in der obigen Funktion "Screenshot()" hängen.Hat jemand eine Idee?
Liegt dies evtl. an meiner globalen Deklaration von Stream?
Ich würde ja die Deklaration und die Erstellung des Streams in Screenshot() machen, aber ich brauche ja auch außerhalb dieser Funktion noch einmal den Zugriff auf Stream.Danke schon mal!
-
"Bleibt hängen" ist nicht sehr aussagekräftig.
Ggf. solltest du mal den Code prüfen, mit dem du "außerhalb dieser Funktion noch einmal den Zugriff auf Stream" nimmst.
-
Außerhalb von "Screenshot" ist der Code, den ich unter "Screenshot" gepostet habe. Diese Anweisungen stehen in der ServerSocket1ClientRead-Routine.
Auch wenn ich nur dort die AnweisungStream->Position=0;
angebe, kommt beim 2. Durchlauf danach keine Reaktion mehr. Habe zum Testen nach "Stream->Position=0;" eine ShowMessage-Anweisung eingefügt. Es kommt keine Message mehr beim 2. Durchlauf.
Der Memorystream wird doch beim Starten der Anwendung einmal erzeugt. Mit Clear() wird der Stream nach der Übertragung doch wieder rückgesetzt (Inhalt gelöscht), und kann beim 2.mal wieder bearbeitet werden so wie beim 1.mal (nach seiner ursprünglichen Erstellung). Oder habe ich das falsch verstanden? Muss der Stream erst wieder irgendwie initialisiert werden?
Oder gibt es eine Alternative zum Stream, aber so, dass der Screenshot ohne in einer Datei zwischenzuspeichern, übertragen wird?Achso, noch eine Ergänzung:
Die Anwendung (server) ist übrigens ein Service. Starte ich nach dem 1. erfolgreichen Durchlauf (nach dem 1. übertragenen Screenshot) den Service neu, dann funktioniert das Ganze wieder einmal, aber nicht ein 2.mal hintereinander. Ist definitiv ein Stream-Problem!
-
So, habe jetzt mal folgendes geändert:
In der Unit des Socketservers:public: // Anwender-Deklarationen __fastcall TService1(TComponent* Owner); TServiceController __fastcall GetServiceController(void); friend void __stdcall ServiceController(unsigned CtrlCode); TMemoryStream *Stream; void Screenshot(void);
In der ServerSocketClientRead Routine:
Stream = new TMemoryStream ; //Speicher für Screenshot-Stream erzeugen
Damit wird ein Stream für die Screenshotübertragung erzeugt, sobald der Client ein bestimmtes Kommandozeichen sendet.
Screenshot klappt danach prima. Der Screenshot wird einwandfrei übertragen, um am Ende unterbricht der Client die Socketverbindung.
Beim Server wird daraufhin das Onclientdisconnect-Ereignis ausgelöst, in dessen Routine ich mitdelete Stream;
den Speicher freigeben möchte. Und genau diese Anweisung funzt nicht!! Ein unmittelbar danach folgendes
Form1->Label1->Caption=("Stream gelöscht");
wird gar nicht mehr ausgeführt!
Was soll das? Hilfffe!