Reading image data from client using Indy command handler

1.1k views Asked by At

I have a small client-server application project using Indy 9. My server application is using 'command handler' to handle client's command. In this case my client application using writeLn procedure to send command and data, which is text based. For example:

IdTcpClient1.WriteLn('cmd1'+'#'+'hello server');

note: 'cmd1' is a command, '#' is command delimiter, and 'hello server' is the data

In order to handle this command (cmd1), my server application has a procedure as follows:

procedure TForm1.IdTcpServer1cmd1Command(Asender:TIdCommand);
var
  s: string;
begin   
  if ( Assigned(ASender.Params) ) then
  begin
    s:= Asender.Param[0];
    ...............
    ...............
  end;
end;

So far everything is fine. The problem is that I want to add a feature so that my server application is able to request and receive a JPEG_image from client. If client send this image using: WriteStream procedure, for example:

IdTcpClient1.WriteStream(MyImageStream);

How then the the server handle this event considering that there is no specific command to it (such as 'cmd1' in this example)?

2

There are 2 answers

3
Remy Lebeau On BEST ANSWER

You would simply call ReadStream() in the command handler, eg:

IdTcpClient1.WriteLn('JPEG');
IdTcpClient1.WriteStream(MyImageStream, True, True); // AWriteByteCount=True

procedure TForm1.IdTcpServer1JPEGCommand(ASender: TIdCommand);
var
  Strm: TMemoryStream;
begin   
  ...
  Strm := TMemoryStream.Create;
  try
    ASender.Thread.Connection.ReadStream(Strm); // expects AWriteByteCount=True by default
    ...
  finally
    Strm.Free;
  end;
  ...
end;

Alternatively:

IdTcpClient1.WriteLn('JPEG#' + IntToStr(MyImageStream.Size));
IdTcpClient1.WriteStream(MyImageStream); // AWriteByteCount=False

procedure TForm1.IdTcpServer1JPEGCommand(ASender: TIdCommand);
var
  Size: Integer;
  Strm: TMemoryStream;
begin   
  ...
  Size := StrToInt(ASender.Params[0]);
  Strm := TMemoryStream.Create;
  try
    if Size > 0 then
      ASender.Thread.Connection.ReadStream(Strm, Size, False); // AWriteByteCount=True not expected
    ...
  finally
    Strm.Free;
  end;
  ...
end;
0
Arioch 'The On

How then the the server handle this event

So what is you actually want to learn ? What is your actual question ?

  • If you want to know how your server would behave - then just run your program and see what happens.
  • If you want to know how to design your server and client, so client could upload a picture to server - then ask just that.

I think that the proper thing to do would be adding the command "picture-upload" with two parameters: an integer token and a jpeg stream.

When the server would reply to cmd1 command, if it would need, it would generate and attach a unique integer token, asking the client to upload the screenshot.

When client would receive this reply, it would parse it, and if the token would be found - would issue one more command, a specially designed "picture-upload#12345" (where 12345 replaced with actual token value) followed by the picture itself. The server would then use the token value to know which client and why did the upload.

PS. though personally I think you'd better just use standardized HTTP REST rather than making your own incompatible protocol.