Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi indy10 / TCPServer /TCPClient ->Datei versenden (https://www.delphipraxis.net/111416-indy10-tcpserver-tcpclient-datei-versenden.html)

ManuMF 7. Apr 2008 13:59

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Ich weiß nicht, ob es in diesem Fall nützlich ist, aber vor einiger Zeit habe ich mich mal ans Senden per TCP und Indy 10 gemacht, und dazu auch was für die CodeLib aufbereitet. Du findest den Code hier, vielleicht hilft dir ein Teil daraus (Stichwort Stream) weiter :)

cherry 7. Apr 2008 14:04

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Danke für deine schnelle Antwort...
... und wieder sind mir einige Lichter aufgegangen... habe aber leider immer noch div. Probleme...

Also, was ich will ist erstmal folgendes...

- Programm#1 will Programm#2 eine Datei schicken. Und sendet (cmd 1) an Prg#2
- Programm#2 erhält den Command 1 (jmd will datei senden)
- Programm#2 akzeptiert (cmd 2) oder lehnt Datei ab (cmd 3)
- Programm#1 wenn Prg#1 (cmd 2) erhält versucht es Datei an Prg#2 zu senden. Wenn (cmd 3) dann abbrechen.

Dabei ist Programm#1 und Programm#2 genau dasselbe... läuft einfach auf unterschiedlichen Rechnern...
Die Programm sollen die Informationen so austauschen, dass das andere immer weiss was das andere macht.

Wenn ich das jetzt so mache wie du mir vorschlägst:

Delphi-Quellcode:
.. try
    // Daten im Buffer ? 
    tmpClient.LastCmd := AContext.Connection.Socket.ReadLn(#$A,Settings.CmdReadTimeOut,Settings.CmdMaxLength);
  except
    tmpClient.LastCmd := '';
  end;
  // Da das OnExecute des Server immer wieder eintritt bis der Client nicht mehr verbunden ist kann der obere Teil als
  // allgemeingültig bezeichnet werden. Je nach empfangenen Daten/Kommando jetzt weiter vorgehen

  // z.B.
  Case tmpClient.LastIntCommand of
    // 
  end;
  // oder
  if tmpClient.LastCmd = 'YXZ' then begin

  end;
  // ...
Dann überschreibts ja immer gleich tmpClient.LastCmd...
Wie kann ich nun z.B. den Namen der Datei schicken?! usw.

Es müsste ja irgendwie möglich sein zuerst einen befehl zu schicken und dann noch weitere Parameter z.b. Filename...
oder dann beim uploaden den befehl z.b (cmd 2) für upload und dann den stream...

Irgendwo hab ich noch ne grosse lücke!

Gruss

cherry 9. Apr 2008 06:13

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Allen vielen Dank für eure Hilfe...

Fürs erste hab ichs nun hinbekommen, scheint jedenfalls zu funktionieren. Eine kleine Frage hätte ich da aber noch, wie kann man nun die Progressbar des "uploaders" (TCPServer) anzeigen lassen?

hier mein aktueller code:

Delphi-Quellcode:
// SEND FILE / ACCEPT INCOMMING FILE (same button)
procedure TForm1.EButton2Click(Sender: TObject);
begin
  if EButton2.Caption = 'upload' then
  begin
    if OpenDialog1.Execute then
    begin
      try
        uploadfilepath := OpenDialog1.FileName;
        EButton2.Enabled := False;
        EButton5.Enabled := False;
        TCPClient.Connect;
        // upload file
        TCPSendCmd(CmdUploadFile);
        TCPClient.IOHandler.WriteLn(ExtractName(uploadfilepath));
        Log(msg001);
        Log('wait for client reply...');
      except
        on e:Exception do
        begin
          Log(e.Message);
          EButton2.Enabled := True;
        end;
      end;
    end;
  end
  else
  begin
    try
      ButtonCaption('receive');
      EButton2.Enabled := False;
      EButton4.Enabled := False;
      EButton5.Enabled := False;
      TCPClient.Connect;
      // accept file
      TCPSendCmd(CmdRecFileOK);
    except
      on e:Exception do
        Log(e.Message);
    end;
  end;
end;
und

Delphi-Quellcode:
procedure TForm1.TCPServerExecute(AContext: TIdContext);
var
  FSTream: TFileStream;
  df: String;
  tmpClientData : TClientData;
begin

  if not assigned(AContext.Data) then
  begin
    AContext.Connection.Disconnect;
    exit;
  end;

  // read clientdata
  try
    tmpClientData := TClientData(AContext.Data);
  except
    AContext.Connection.Disconnect;
    exit;
  end;

  // check state
  if (tmpClientData.Status = cCSGoing2Disconnect) or
     (tmpClientData.Status = cCSDisconnected) then
  begin
    AContext.Connection.Disconnect;
    exit;
  end;

  // get command
  try
    tmpClientData.LastCmd := AContext.Connection.Socket.ReadLn(#$A,5000,1024);
  except
    tmpClientData.LastCmd := '';
  end;

  // check the old command
  case tmpClientData.LastIntCmd of
    // GUY WANTS TO SEND FILE
    1:
    begin
      savefilepath := DestinationEdit.Text + AContext.Connection.IOHandler.ReadLn;
      Log(AContext.Binding.PeerIP+' wants to send file: "'+ExtractName(savefilepath)+'"');
      ButtonCaption('receive');
      EButton4.Enabled := True;
    end;
    // UPLOAD FILE
    2:
    begin
      Log('upload file...');
      TCPSendCmd(4);
      try
        // upload
        FStream := TFileStream.Create(uploadfilepath, fmOpenRead or fmShareDenyWrite);
        TCPClient.IOHandler.Write(FStream,0,true);
        // disconnect
        AContext.Connection.Disconnect;
        if TCPClient.Connected then
          TCPClient.Disconnect;
        tmpClientData.Status := cCSDisconnected;
      finally
        FStream.Free;
      end;
      Log('successfully uploaded');
      ButtonCaption('upload');
      EButton4.Enabled := False;
      EButton2.Enabled := True;
      EButton5.Enabled := True;
    end;
    // GUY REFUSED FILE
    3:
    begin
      Log('guy refused to download file');
      // disconnect
      AContext.Connection.Disconnect;
      if TCPClient.Connected then
        TCPClient.Disconnect;
      tmpClientData.Status := cCSDisconnected;
      ButtonCaption('upload');
      EButton4.Enabled := False;
      EButton2.Enabled := True;
      EButton5.Enabled := True;
    end;
    // DOWNLOAD FILE
    4:
    begin
      try
        if FileExists(savefilepath) then
        begin
          Log('file was already existing');
          df := savefilepath;
          DeleteFile(df);
          Log('old file deleted!');
        end
        else if DirectoryExists(ExtractFilePath(savefilepath)) = false then
        begin
          CreateDir(ExtractFilePath(savefilepath));
          Log('directory "'+ExtractFilePath(savefilepath)+'" created');
        end;
        Log('download...');
        try
          // download
          FStream := TFileStream.Create(savefilepath, fmCreate);
          AContext.connection.IOHandler.ReadStream(fstream);
          // disconnect
          AContext.Connection.Disconnect;
          if TCPClient.Connected then
            TCPClient.Disconnect;
          tmpClientData.Status := cCSDisconnected;
        finally
          FStream.Free;
        end;
        Log('file successfully downloaded!');
        ButtonCaption('upload');
        EButton4.Enabled := False;
        EButton2.Enabled := True;
        EButton5.Enabled := True;
      except
        on e:Exception do
          Log(e.Message);
      end;
    end;
    // RECEIVE CHAT MESSAGE
    5:
    begin
      Log(AContext.Binding.PeerIP+': '+AContext.Connection.IOHandler.ReadLn);
      AContext.Connection.Disconnect;
    end;
  end;
end;
hehe

Delphi-Quellcode:
procedure TForm1.TCPSendCmd(Cmd: Byte);
begin
  try
    TCPClient.IOHandler.WriteLn(IntToStr(Cmd));
  except
    on e:Exception do
      Log(e.Message);
  end;
end;

mleyen 18. Apr 2008 07:53

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Hi,
so jetzt frage ich doch nochmal...

Was ich will:
Ich will ein TJpegImage oder TBitmap in einen Stream speichern und dann den Stream über TCPClient an den TCPServer senden. (Höhrt sich einfach an, treibt mich aber noch in den Wahnsinn)
Das schlimme dabei ist, ich benutze Indy 10 und da gibt es keinen 'WriteStream'! :roll:

Wie ich es bisher umgangen hab:
Ich hab das JPG in eine Datei gespeichert und die Datei dann versendet, empfangen, geladen, gelöscht und das funktioniert auch perfekt nur ist es halt regelrecht lahm aufgrund der vielen Festplattenzugriffe.

Bisher hab ich folgendes:
Delphi-Quellcode:
// Client sendet den Stream
memStream := TMemoryStream.Create;
jpgTmp.SaveToStream(memStream);
memStream.Position := 0;
FClient.IOHandler.Write(memStream);

// Server epfängt den Stream
memStream := TMemoryStream.Create;
AContext.Connection.IOHandler.ReadStream(memStream,FileSize);
memStream.Position := 0;
jpgTmp.LoadFromStream(memStream);
Bei der Filesize weiß ich, das sie den richtigen Wert enthält.
Wenn ich aber das Debug hängt der Client in 'Write' und der server in 'ReadStream' und weiter gehts nicht mehr. :gruebel:
Oder habe ich eventuell jetzt schon einen Fehler gemacht? :pale:


Zitat:

Zitat von DataCool
Zum Senden einer Datei via Stream; Ich kann Dir jetzt nicht mit 100% Sicherheit sagen wie's gemacht wird,
weil ich meine akztuellen Projekte alle noch in Indy9 habe und bald erst mit dem portieren anfange.
Was ich aber festgestellt habe ist das es in Indy10 kein "WriteStream" mehr gibt, obwohl ein "ReadStream"
gibt. Ich habe aber auch gesehen das es bei Indy10 jetzt ein WriteFile gibt und wenn man sich den Source dazu anschaut :

Delphi-Quellcode:
function TIdIOHandler.WriteFile(const AFile: String; AEnableTransferFile: Boolean): Int64;
var
//TODO: There is a way in linux to dump a file to a socket as well. use it.
  LStream: TIdStream;
begin
  EIdFileNotFound.IfFalse(Sys.FileExists(AFile), Sys.Format(RSFileNotFound, [AFile]));
  LStream := TReadFileExclusiveStream.Create(AFile); try
      Write(LStream);
      Result := LStream.Size;
  finally Sys.FreeAndNil(LStream); end;
end;
^^ Da könntest Du Dir die Vorgehensweise abschauen.

Das ist einer der wenigen Sachen die ich noch nicht ausprobiert habe, da ich nicht weiß wie ich den LStream 'Createn' soll, da als Parameter immer ein Dateipfad benötigt wird anstatt einen Stream.


Ich hoffe irgendwer hat eine Lösung parat bzw kann mir helfen, dass ich den Stream versendet und empfangen bekomm.
Danke schonmal!

STS301 18. Apr 2008 07:56

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
schau dir bitte den Beitrag von ManuMF #21 an, das wird bestimmt helfen

mleyen 18. Apr 2008 08:10

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Zitat:

Zitat von STS301
schau dir bitte den Beitrag von ManuMF #21 an, das wird bestimmt helfen

Leider nicht, hab ich auch schon ausprobiert.

Die Unit 'IdStreamVCL' enthält bei mir keinen Typ 'TidStreamVCL' sondern nur 'TIdStreamHelperVCL'. (Welcher nichtmal einen Parameter im Create hat)

STS301 18. Apr 2008 08:34

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
schau dir den Beitrag #10 an

mleyen 18. Apr 2008 08:58

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Mit dem Post wolltest du wahrscheinlich auf diesen Thread hinweisen.
Das ist aber genau der murks den ich momentan mache. (wie bereits erwähnt)
Da werden keine Daten direkt versendet per Stream, da wird erst in eine Datei gespeichert, die Datei wird versendet und beim Empfänger gespeichert, Beim empfänger wird die Datei geladen und dann erst hat man den Stream/Inhalt.

Das ganze hin und hergespeichere kann man sich doch bestimmt ersparen indem man direkt einen Stream versendet, nur wie? :cry:

Naja ich hau jetzt Indy 10 raus und Indy 9 rein.
Dann hab ich auch mein 'WriteStream' und die Welt ist heile... :thumb: (hoffentlich^^)

Danke trotzdem!

STS301 18. Apr 2008 09:43

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
für Indy 9 wirst du im Delphitreff forum viel finden

DataCool 18. Apr 2008 13:21

Re: indy10 / TCPServer /TCPClient ->Datei versenden
 
Hi,

für Indy9 habe ich ein komplettes Bsp. von mir fertig :

Beam me up

Greetz DataCool


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:01 Uhr.
Seite 3 von 3     123   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz