Entwickler-Ecke

Internet / Netzwerk - TImage über Indy verschicken...


g1o2k4 - Fr 11.09.09 18:37
Titel: TImage über Indy verschicken...
tag.

ich hab mit indy noch nie gearbeitet und bin froh das ich schon nen chat hinbekommen habe :P die bedienung von indy scheint ja simple zu sein, aber der funktionsumfang ist so riesig, dass ich mich bis jetzt kaputt gesucht habe um das zu schaffen.
daher die frage, wie ich dadran gehn soll.

in welches format muss ich das timage konvertieren und was muss ich mit indy tun, damit es vom clienten zum server gelangt?
ich benutze ganz normal einmal einen IdTCPClient und nen IdTCPServer und es soll vom client zum server geschickt werden. ansonsten hab ich bis auf port und host nichts eingestellt und alles bei den standard configs belassen.

vielleicht sollte ich noch erwähnen dass ich indy 10 neueste version benutze. hab einige beispiele gefunden die aber nix taugen weil die komponenten anders heißen oder gar nicht vorhanden sind.


g1o2k4 - Fr 11.09.09 22:16

kleines update. hab durch suche in foren ein stück code gefunden der bis jetzt am besten geklappt hat:

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:
//senden
procedure TForm2.Button5Click(Sender: TObject);
var
  FStream: TFileStream;
begin
  FStream := TFileStream.Create('C:\client.gif', fmOpenRead);
  tcpclient.Connect;
  try
    tcpclient.IOHandler.Write(Fstream,0,true);
  finally
    tcpclient.Disconnect;
  end;
  FreeAndNil(FStream);
end;

//empfangen
procedure TForm2.TCPServerExecute(AContext: TIdContext);
var
  FSTream: TFileStream;
begin
  FStream := TFileStream.Create('C:\server.gif', fmCreate);
  try
    AContext.connection.IOHandler.ReadStream(fstream, -1, true);
  finally
    AContext.connection.Disconnect;
  end;
  FreeAndNil(FStream);
end;


problem ist nur, dass der anfang der datei die ankommt überhaupt nicht mehr mit dem der gesendeten überein, der anfang ist total kaputt und die neue datei ist auch nur noch halb so groß. jemand ne idee?


g1o2k4 - Sa 12.09.09 10:57

also ich bin jetzt auf jedenfall schonmal so weit, dass ich weiß dass die ersten 23 zeichen mit meiner sende und empfangsfunktion verloren gehen. was ist da nur kaputt?


Dude566 - Sa 12.09.09 11:00

Erst nach 24 Stunden ist das Pushen erlaubt! :wink:


g1o2k4 - Sa 12.09.09 11:58

user profile iconDude566 hat folgendes geschrieben Zum zitierten Posting springen:
Erst nach 24 Stunden ist das Pushen erlaubt! :wink:


ok dann werd ich jetzt nur noch editen.


Dude566 - Sa 12.09.09 12:33

Könntest du denn bitte mal Zeigen wie du Nachrichten versendest etc. ich habe damit noch nicht gearbeitet und würde es gerne sehen.


Hidden - Sa 12.09.09 12:48

Hi :)

TImage ist jedenfalls schonmal eine visuelle Komponente, die zu Verschicken macht keinen Sinn. Was du verschicken kannst, sind Bilddateien - dort dann die bekannten Formate wie png, jpg, (((bmp))).

PS: TImage verwendet übrigens Bitmaps.

mfG,


g1o2k4 - Sa 12.09.09 13:14

ich habs jetzt geschafft, mehr durch probieren als durch verstand :P

ich habs debuggt und gemerkt dass in indy immer die ersten paar byte benutzt werden um die stream länge festzustellen daher schicke ich jetzt er über writeln die streamlänge und dann den stream. so klappt es jetzt (varianten mit file oder memorystream):

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:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
//senden
procedure TForm2.Button5Click(Sender: TObject);
var
  FStream: TFileStream;
  MStream: TMemoryStream;
begin
  //Image1.Picture.Graphic.SaveToFile('.\client.jpg');
  //FStream := TFileStream.Create('.\client.jpg', fmOpenRead);

  MStream := TMemoryStream.Create;
  Image1.Picture.Graphic.SaveToStream(MStream);

  try
    { Senden }
    with TCPClient do
    begin
      Connect;
      try
        IOHandler.WriteLn(IntToStr(MStream.Size));
        IOHandler.WriteBufferOpen;
        IOHandler.Write(MStream);
        IOHandler.WriteBufferFlush;
        IOHandler.WriteBufferClose;
        // Socket.Write(FStream);
      finally
        Disconnect;
      end;
    end;
  finally
    FreeAndNil(MStream);
  end;
end;

//emfpangen
procedure TForm2.TCPServerExecute(AContext: TIdContext);
var
  FStream: TFileStream;
  MStream: TMemoryStream;
  SizeOfIncomingStream: Integer;
  IDS: TIdStreamHelperVCL;
  filename: string;
begin
  //filename := '.\server.jpg';
  //FStream := TFileStream.Create(filename, fmCreate);

  MStream := TMemoryStream.Create;

  try
    { Empfangen }
    with AContext.Connection do
    begin
      try
        // SizeOfIncomingStream := Socket.ReadLongInt(true);

        SizeOfIncomingStream := strtoint(IOHandler.ReadLn);
        IOHandler.ReadStream(MStream, SizeOfIncomingStream, true);
        // Socket.ReadStream(fstream, SizeOfIncomingStream, false);

      finally
        Disconnect;
      end;
    end;
  finally
    FreeAndNil(MStream);
  end;

  //Image1.Picture.Graphic.LoadFromFile('.\server.jpg');
  Image1.Picture.Graphic.LoadFromStream(MStream);
end;


@Dude566: und um text zu senden funktioniert so:

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:
//senden
procedure TForm2.Button5Click(Sender: TObject);
begin
    with TCPClient do
    begin
      Connect;
      try
        IOHandler.WriteLn('Hallo Welt!');
      finally
        Disconnect;
      end;
    end;

end;

//emfpangen
procedure TForm2.TCPServerExecute(AContext: TIdContext);
begin

    with AContext.Connection do
    begin
      try
        Memo1.Text := IOHandler.ReadLn;
      finally
        Disconnect;
      end;
    end;


end;


du brauchst lediglich eine tcpserver und eine tcpclient komponente und musst dort noch die einstellungen für host und port vornehmen. dann sendest du über einen buttonklick zum server. und im serverexecute event liest du es aus.


Narses - So 13.09.09 10:21

Moin!

user profile icong1o2k4 hat folgendes geschrieben Zum zitierten Posting springen:
@Dude566: und um text zu senden funktioniert so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
[...]
//emfpangen
procedure TForm2.TCPServerExecute(AContext: TIdContext);
begin
    with AContext.Connection do
    begin
      try
        Memo1.Text := IOHandler.ReadLn; // Achtung! Anderer Thread-Context! Das ist verboten!
      finally
        Disconnect;
      end;
    end;
end;
Auf keinen Fall diesen Ansatz weiter verfolgen, da - im Gegensatz zu den Sockets - der Indy-TCPServer mutithreaded ist, so dass hier ein Zugriff auf VCL-Komponenten ausserhalb des Main-(GUI-)Threads erfolgt! Ein Zugriff auf VCL-Komponenten muss z.B. mit Synchronize() synchronisiert werden.

cu
Narses