Entwickler-Ecke

Internet / Netzwerk - Indy Stream Problem (Stream zu lange)


Softchaos67 - Do 20.01.05 09:48
Titel: Indy Stream Problem (Stream zu lange)
Hallo,
ich habe eine abgewandelte Client und Server Version des Indy Beispiel "ImageServer"
programmiert.
Von TIDTcpServer habe ich eine eigene Klasse abgeleitet, um spezielle Funktionen zu implementieren.
Nun das Problem: Beim Senden des Streams scheint alles OK zu sein.
Beim Client ist der Stream aber immer genau 33 Byte zu lange.
Woran könnte das liegen?

Der Server(Execute):

Delphi-Quelltext
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:
var
    s, sCommand, sAction : string;
    memStream :TMemoryStream;
    tBM : tbitmap;
    jpg :TJPEGImage;
begin
   CS.Enter;
   try
       s := uppercase(AThread.Connection.ReadLn);
       sCommand := copy(s,1,3);
       sAction := copy(s,5,length(s));
       if sCommand = 'SRN' then begin
          // take snapshot
          lstRequests.add('Taking screen snap shot');
          tBM := TBitmap.Create;
          ScreenShot(0,0,Screen.Width,Screen.height,tBM);
          jpg := TJPEGImage.Create;
          jpg.Performance := jpBestQuality;
          jpg.CompressionQuality := 100;   // hier frei wählbare kompression (0-100)
          jpg.Assign(tBM);
          memStream := TMemoryStream.Create;
          jpg.SaveToStream(memStream);
          memStream.Position := 0;

          // open file stream to image requested

          // copy file stream to write stream
          AThread.Connection.OpenWriteBuffer;
          AThread.Connection.WriteStream(memStream);
          AThread.Connection.CloseWriteBuffer;

          AThread.Connection.Disconnect;
          // free the file stream
          FreeAndNil(memStream);

          tBm.FreeImage;
          FreeAndNil(tBM);
          FreeAndNil(jpg);

       end else if (sCommand <> 'MSG'and (sCommand <> 'LST'and (sCommand <> 'SRN'then begin
          lstRequests.add('ERR : Unknown command / action');
          AThread.Connection.WriteLn('ERR : Unknown command / action');
          AThread.Connection.Disconnect;
      end;
   except
//     on E : Exception do ShowMessage(E.Message);
   end;
   CS.Leave;
end;


und hier der Client:

Delphi-Quelltext
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:
procedure TfrmLogVerw.Button2Click(Sender: TObject);
var
   MemoryStream : TMemoryStream;
begin
  inherited;
  try

     with MyTCPClient do begin
        if connected then Disconnect;
       Host := ColorStrGrd1.Cells[8,ColorStrGrd1.Row];
       Port := 6999;
       Connect;
       WriteLn('SRN:');
       MemoryStream := TMemoryStream.Create;
       while connected do ReadStream(MemoryStream,-1,true);
       Disconnect;
       MemoryStream.Position := 0;
       jpg := TJPEGImage.Create;
       jpg.LoadFromStream(MemoryStream); // Das geht schief weil der Stream 
                                         // 33 Byt zu lange
       Image1.Picture.Bitmap := JPEGtoBMP(jpg);
       FreeAndNil(MemoryStream);
       FreeAndNil(jpg);
    end;
   except
      on E : Exception do
          ShowMessage(E.Message);
   end;

Hat jemand ne Idee?
Danke
Gruss
Matthias


maxk - Do 20.01.05 15:37

Hallo,
mich stört ein bisschen der folgende Code:

Delphi-Quelltext
1:
2:
       while connected do ReadStream(MemoryStream,-1,true);  
       Disconnect;
Dort weist du Delphi an, solange in den Stream zu lesen, bis das Kommando das solange liest wie eine Verbindung besteht, die Verbindung nicht trennst - mit anderen Worten, wenn du aus der Schleife rauskommst, besteht keine Verbindung mehr. Anschließend trennst du die Verbindung. Eigentlich muss da eine Exception auftreten. Vielleicht solltest du den Code ein wenig ändern:

Delphi-Quelltext
1:
2:
3:
4:
       MemoryStream.Size := 0;              // Man weiss ja nie....
       MemoryStream.Position := 0;          // ...was Delphi so intern macht ;)
       ReadStream(MemoryStream, -1, True);  // Jetzt wird alles gelesen, was die Verbindung hergibt
       // Ein Disconnect können wir uns sparen, da die Verbindung 100% nicht mehr existiert!


Gruß,
maxk


Softchaos67 - Do 20.01.05 15:50

Danke für den Hinweis.
Funzt auch aber selbe Fehlermeldung.
Wenn ich den Stream auf Position 33 setzte, dann kann ich den Stream lesen!

Delphi-Quelltext
1:
2:
3:
       memStream.Position := 33;      //Stream ist 33 Byte zu lange
       jpg := TJPEGImage.Create;
       jpg.LoadFromStream(memStream);

Also wo kommen die 33 Byte am Beginn des Stream her??


maxk - Do 20.01.05 16:05

Keine Ahnung, guck doch mal, was drin steht:

Delphi-Quelltext
1:
2:
3:
4:
 // Buf ist ein String!
 SetLength(Buf,33);
 MemoryStream.Position:=0;
 MemoryStream.ReadBuffer(Buf[1],33);


Als Lösung folger Vorschlag: Deine 33 Bytes sind ein Überbleibsel von irgendeinem anderen Befehl, der vor dem Screenshot nicht verarbeitet wurde. Du solltest also mal prüfen, ob du im Server z.B. eine Greetingmeldung o.ä. eingestellt hast. Wenn du vor das WriteLn('SRN:') aber noch folgendes schreibst, sollte es eigentlich gehen (guck trotzdem woher der Fehler kommt!).

Delphi-Quelltext
1:
2:
     if Socket.Readable(0then CurrentReadBuffer; // Falls es noch Zeichen gibt, hole sie ab
     WriteLn('SRN:'); // Request senden


maxk


Softchaos67 - Do 20.01.05 16:22

Im Buffer stand "Greetings from IServer...." :shock:
Das wars!
GreetingText... da muss man erstmal drauf kommen :wink:

mache jetzt ein Readln for dem Streamlesen und schon gehts...
Danke vielmals!
Gruss
Matthias


maxk - Do 20.01.05 19:03

Freut mich, dass es jetzt geht. Überlege aber, ob du den Greetingtext wirklich verwenden willst. Evtl. kannst du ihn dir auch einfach sparen (ich auch ganz gut für den Traffic).

maxk


Softchaos67 - Fr 21.01.05 09:04

Ja, ich weiss ja mit welchem Server ich mich vebrinde.
Der GreetinText fliegt raus.
Danke nochmals.
Gruss
Matthias