Search code examples
androidimagedelphitcpindy

how to send all images in folder to clinet using tcp server client?


how to send multiple images from a specific folder from client to server. I managed to send only one image! i used this code

client code

fn := 'C:\Documents and Settings\admin\Desktop\11/65474.jpg';
fs := TFileStream.Create(fn, fmOpenRead);
Host := Edit1.Text;
idTCPClient1.Connect;
IdTCPClient1.IOHandler.Write(fs);

Server Code

procedure TForm3.IdTCPServer1Execute(AContext: TIdContext);
var
  fs: TFileStream;       
begin
  fs := TFileStream.Create('C:\Documents and Settings\Admin\Desktop\pic\.png', fmCreate);   
  AContext.Connection.IOHandler.ReadStream(fs, -1, True);
end;

the idea is to send all imges in folder to a client from one tcpserver.idTCPCLient plz help?? im sorry for noob question.


Solution

  • Your calls to TIdIOHandler.Write(TStream) and TIdIOHandler.ReadStream() are mismatched.

    By default, ReadStream() expects the stream size to be sent before the stream data. When AByteCount is -1 and AReadUntilDisconnect is False (the default parameter values), ReadStream() reads the first 4 or 8 bytes (depending on the TIdIOHandler.LargeStream property) to know how many bytes to read into the TStream. However, you are setting AReadUntilDisconnect to True instead, so AByteCount is ignored, and ReadStream() will not exit until the client disconnects from the server. That is the wrong functionality to use if you need to receive more than one stream (or anything else after the first stream, for that matter).

    By default, the AWriteByteCount parameter of Write(TStream) is False, so it does not send the stream size. When AWriteByteCount is set to True instead, Write() sends the stream size using 4 or 8 bytes (depending on the TIdIOHandler.LargeStream property) before then sending the stream content.

    So, you are telling the client NOT to send the stream size, and telling the server to IGNORE the stream size (OK for the example you showed, but not OK for your intended goal), but you are also telling the server to WAIT until the client disconnects to signal the end of the stream, but the client is not disconnecting after sending the stream.

    Try something more like this instead:

    idTCPClient1.Host := Edit1.Text;
    idTCPClient1.Connect;
    ...
    
    for fn in TDirectory.GetFiles('C:/1/') do
    begin
      fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
      try
        IdTCPClient1.IOHandler.WriteLn(ExtractFileName(fn));
        IdTCPClient1.IOHandler.Write(fs, 0, True);
      end;
        fs.Free;
      end;
    end;
    ...
    idTCPClient1.Disconnect;
    

    procedure TForm3.IdTCPServer1Execute(AContext: TIdContext);
    var
      fn: string;
      fs: TFileStream;       
    begin
      fn := 'some base path\' + ExtractFileName(AContext.Connection.IOHandler.ReadLn);
      fs := TFileStream.Create(fn, fmCreate);
      try
        try
          AContext.Connection.IOHandler.ReadStream(fs, -1, False);
        finally
          fs.Free;
        end;
      except
        DeleteFile(fn);
        raise;
      end;
    end;
    

    Of course, there is a very bare bones protocol. A more flexible protocol would use a command/response model so a client can send different types of commands other than file transfers, a client can ask permission to send a file before actually sending it, the server can send a confirmation if a file was successfully received or not, etc.