Page 1 of 2 1 2 LastLast
Results 1 to 15 of 25

Thread: Client Server verbinding, Hoe Bestand versturen ?

  1. #1

    Client Server verbinding, Hoe Bestand versturen ?

    Ik ben met een Client Server verbinding bezig, en gebruik daarvoor FMX en deze Componenten:
    IdTCPServer
    IdTCPClient
    IdThreadComponent

    Het versturen van een Tekst heb ik werkend, maar hoe kan ik het beste een bestand versturen ?

  2. #2
    zal oa afhangen van de grootte van je bestand. Maar in essentie is het natuurlijk gewoon een reeks bytes die je moet versturen. Maar misschien is iets als ftp een beter protocol als je bestanden wilt versturen en zelf wilt knutselen.

    Er zijn vele middleware frameworks die dit gewoon voor je regelen. KbmMW is er bv zo een die een fileservice heeft out of the box. KbmMW werkt ook met fmx, inclusief de mobile platforms. Kim is zelf heel actief bezig met projecten op mobile, met gebruik van FMX en kbmMW.

  3. #3
    Hierbij de code die ik nu heb, waarmee ik een Tekst kan zenden:
    https://www.uploadarchief.net:443/fi...ngst_zijde.zip
    https://www.uploadarchief.net:443/fi...zend_zijde.zip

    Hoe zou ik deze aan moeten passen om een bestand te kunnen verzenden ?

  4. #4
    Ik probeer het zo werkend te krijgen:

    Zend Zijde:
    Code:
    procedure TForm1.Button4Click(Sender: TObject);
    var
      FileName: string;
      Strm: TStream;
    begin
      FileName := 'C:\=== DATA ===\20190925_155655_001.jpg';
    
      Strm := TFileStream.Create(FileName, fmCreate);
    
      try
        try
         IdTCPClient1.IOHandler.Write(TStream(Strm), 0, True);
    
        finally
          Strm.Free;
        end;
      except
        //DeleteFile(FileName);
        raise;     //Verhogen
      end;
    
      Memo1.Lines.Add('ok');
    
    end;

    Ontvangst Zijde:
    Code:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
     Port          : Integer;
     PeerPort      : Integer;
     PeerIP        : string;
     msgFromClient : string;
     msgToClient   : string;
     Received: String; 
    
    begin
     Received := AContext.Connection.IOHandler.ReadLn;
    
     if Received = 'stream' then 
      begin
       AContext.Connection.IOHandler.Write(TStream(AContext.Data), 0, True);
      end;
    
     // ... getting IP address, Port and PeerPort from Client that connected
     peerIP    := AContext.Binding.PeerIP;
     peerPort  := AContext.Binding.PeerPort;
    end;
    Er is connectie tussen de Server en de Client.

    Als ik aan de Zend zijde op Button4 klik, dan krijg ik de melding OK, maar er gebeurd niets meer dan dat het bestand ineens leeg is.
    Wat doe ik allemaal verkeerd, en hoe geef ik aan de Ontvangst zijde op hoe en waar het te ontvangen Bestand moet worden opgeslagen ?

  5. #5
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    MMSoft: stop een header voor je stream met daarin o.a. de size in bytes. In de client lees je de header dan, en dan weet je hoeveel bytes aan filedata je kan ontvangen.

    Ontvangen is wat lastiger, omdat je niet kan wachten tot alle data binnen is. Je moet iedere zoveel kb (ik doe 32kb) de data uit je socket halen en (tijdelijk of permanent) opslaan, tot je alles binnen hebt.

  6. #6
    Waar komt dit voorbeeld vandaan? Ik zie in de verzender .write() staan en in de ontvanger ook. Beide tegelijk schrijven maar de socket lijkt mij niet juist te zijn.

    Volgens mij heeft IOHandler ook een .readstream() en .write() (voor stream) waar het met die headers met size al geregeld is. Je moet dan wel de juiste parameters gebruiken.

    Zie bv.
    https://stackoverflow.com/questions/...nd-idtcpserver

  7. #7
    Waar komt dit voorbeeld vandaan?
    Dit is een mengeling van meerdere voorbeelden (die allemaal anders waren).

  8. #8
    Quote Originally Posted by MMSoft View Post
    Dit is een mengeling van meerdere voorbeelden (die allemaal anders waren).
    Dat zal dan de reden zijn dat het niet werkt.
    Als je aan beide kanten het gedeelte pakt om te verzenden dan zal nooit iemand wat ontvangen

  9. #9
    Code:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
     Port          : Integer;
     PeerPort      : Integer;
     PeerIP        : string;
     msgFromClient : string;
     msgToClient   : string;
     Received: String; 
     ms:TMemoryStream;
    
    begin
    
      try
        ms:=TMemoryStream.Create;
        AContext.Connection.IOHandler.ReadStream(ms);
    
        ms.SaveToFile('C:\=== DATA ===\TEST.jpg');
    
      except
        Memo1.Lines.Add( 'Failed to receive'  );
      end;
    
    end;


    Code:
    procedure TForm1.Button4Click(Sender: TObject);
    var
      FileName: string;
      Strm: TStream;
    begin
      FileName := 'C:\=== DATA ===\20190925_155655_001.jpg';
    
      Strm := TFileStream.Create(FileName, fmCreate);
    
      try
        try
         IdTCPClient1.IOHandler.Write(TStream(Strm), 0, True);
    
        finally
          Strm.Free;
        end;
      except
        //DeleteFile(FileName);
        raise;     //Verhogen
      end;
    
      Memo1.Lines.Add('ok');
    
    end;
    Na een Klik op Button4 krijg ik de melding OK, maar bestand '20190925_155655_001.jpg' is daarna weer leeg en er is geen bestand 'TEST.jpg' aangemaakt.

  10. #10
    Nu heb je in de verzend kant dit staan: TFileStream.Create(FileName, fmCreate)
    Met fmCreate maak je een nieuw leeg bestand aan.
    Maar aan de verzendkant wil jij dat bestand toch niet vernietigen net voor verzenden?

    fmCreate
    Create a file with the given name. If a file with the given name exists, open the file in write mode.
    http://docwiki.embarcadero.com/RADSt...g_File_Streams

    Logisch dus dat het bestand aan de verzendkant dus leeg raakt en er geen bestand ontvangen wordt.

  11. #11
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    En AContext.Connection.IOHandler.ReadStream(ms); lees het aantal bytes dat in de komende "readtimeout" ms op de socket beschikbaar is. Het leest niet gegarandeerd het hele bestand.

  12. #12
    Readstream kon dacht ik wel de streamsize inlezen als header. Die moet dan wel meegegeven worden (wat iohandler.write standaard niet doet. Er moet dus ook echt goed maar de parameters gekeken worden. Dus wel of geen header meesturen.

    By default, TIdIOHandler.Write(TStream) DOES NOT send the stream size, but TIdIOHandler.ReadStream() DOES expect a size to be sent. This is one of the rare cases where a pair of write/read methods do not compliment each other.
    https://forum.lazarus.freepascal.org...1522#msg291522

    Wel voor Lazarus maar Indy zal daar niet zo verschillend zijn. Er staan daar wat juiste combinaties.

    Maar goed... de stackoverflow link die ik gaf had ook al een werkend voorbeeld (met verzenden van size).

  13. #13
    Ik heb nu dit, en het bestand wordt niet meer gewist:
    Code:
    procedure TForm1.Button4Click(Sender: TObject);
    var
      FileName: string;
      Strm: TStream;
    begin
      FileName := 'C:\=== DATA ===\20190925_155655_001.jpg';
    
      Strm := TFileStream.Create(FileName, fmOpenWrite);
    
      try
        try
         IdTCPClient1.IOHandler.Write(TStream(Strm), 0, True);
    
        finally
          Strm.Free;
        end;
      except
        //DeleteFile(FileName);
        //raise;     //Verhogen
        Memo1.Lines.Add('Ok 1');
      end;
    
    end;

    Het valt mij nu pas op dat de verbinding meteen verbroken wordt als ik deze opstart, dus nog voordat ik iets verzend.
    Ik gebruik de code zoals in de Zip's, en heb alleen de bovengenoemde wijzigingen erin geplaatst.
    In het begin waarbij ik alleen een String verzond, had ik dit probleem niet.

    Dit krijg ik te zien in de Server:
    12:54: Ontvanger Gestart
    12:54: Client Connected
    12:54: >Port: 20010
    12:54: >PeerIP: 192.168.178.32
    12:54: >PeerPort: 56104
    12:54: Client Disconnected
    12:54: >Port: 20010
    12:54: >PeerIP: 192.168.178.32
    12:54: >PeerPort: 56104
    Last edited by MMSoft; 10-Jul-21 at 20:33.

  14. #14
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Ik heb het even nagelopen, omdat ik die functie ook gebruik, er zit wat code in die de size automatisch leest.

    Dus ik gebruik readstream(strm,<een getal bepaald uit mijn header, bytes available on socket, max 32kb>,false);
    en de automatische size read is readstream(strm,-1,false);

    Brrr. Mijnenveld.

    Delphi Code:
    1. procedure TIdIOHandler.ReadStream(AStream: TStream; AByteCount: TIdStreamSize;  AReadUntilDisconnect: Boolean);
    2.  const    cSizeUnknown = -1;
    3. begin
    4.   if (AByteCount = cSizeUnknown) and (not AReadUntilDisconnect) then begin
    5.     // Read size from connection

    Weet iemand hoe je aan oude embarcadero forum posts kan komen? Die link in die SO is ook al weer dood.

  15. #15
    Er waren volgens mij wel wat pogingen gedaan om het te archiveren maar geen die echt van de grond gekomen is (of nog in de lucht is).

    Voor de >32kb is volgens mij de LargeStream boolean.

    @MMSoft Welke vorm wil je nu gebruiken? Als je 0, true gebruikt in write zoals nu dan moet je het ook bij de ontvangstkant goed ontvangen. Wat heb je daar nu staan? Welke van de twee opties uit deze link hem je nu gebruikt? https://forum.lazarus.freepascal.org...html#msg291522

Page 1 of 2 1 2 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •