Veit Zimmermann
Veit Zimmermann

Reputation: 193

TIdTcpClient has shifted LastCmdResults

I started implementing a system using a client server connection with a TIdCmdTcpServer and a TIdTcpClient. The connection is established fine and communication seems to work in general, too. But LastCmdResults contains always the response of the command issued before the last command. It starts with an empty response for the TcpClient.Connect and then continues with a "welcome" as a response to the first TcpClient.SendCmd ('LIST'). When I issue the LIST command again I get the desired result but for the one before (tested with a counter variable).

Relevant Code Snippets:

Initialising Command Handler

  CmdHandler := TCPCmdServer.CommandHandlers.Add;
  CmdHandler.Name := 'cmhList';
  CmdHandler.Command := 'LIST';
  CmdHandler.OnCommand := Cmd_ListDevices;
  CmdHandler.ExceptionReply.NumericCode := 550;
  CmdHandler.Disconnect := FALSE;

  TCPCmdServer.Active := TRUE;

Command handler event Cmd_ListDevices

procedure TSPM_Server.Cmd_ListDevices (aSender : TIdCommand);
begin
  aSender.Reply.SetReply (200, 'List');
  aSender.Reply.Text.Add ('Device 1');
  aSender.Reply.Text.Add ('Device 2');
  aSender.Reply.Text.Add ('Device 3');
  aSender.SendReply;
end;

Client Side

function TSPM_TCPClient.Connect (var aResponseText : string) : boolean;
begin
  TcpClient.Connect;
  aResponseText := TcpClient.LastCmdResult.Text.Text;
  result := TcpClient.Connected;
end;

function TSPM_TCPClient.RequestList (var aList : string) : integer;
begin
  aList := '';
  result := TcpClient.SendCmd ('LIST');
  if result = 200 then
    begin
      aList := 'CMD: ' + TcpClient.LastCmdResult.DisplayName + sLineBreak
                   + TcpClient.LastCmdResult.Text.Text;
    end;
end;

Anything obviously wrong here?

Upvotes: 1

Views: 327

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597036

LastCmdResults contains always the response of the command issued before the last command

That happens when you have the server setup to send a greeting when a new client connects (see the TIdCmdTCPServer.Greeting property), but your client code is not reading that greeting. The greeting remains in the client's receive buffer until it is read. So, the 1st SendCmd() will read the greeting, then the 2nd SendCmd() will read the response of the 1st SendCmd(), and so on.

After TIdTCPClient.Connect() is successful, call TIdTCPClient.GetResponse() immediately to read the greeting, TIdTCPClient.Connect() will not read it for you, eg:

function TSPM_TCPClient.Connect (var aResponseText : string) : boolean;
begin
  TcpClient.Connect;
  try
    TcpClient.GetResponse(200); // <-- add this!
    aResponseText := TcpClient.LastCmdResult.Text.Text;
    Result := True;
  except
    TcpClient.Disconnect;
    Result := False;
  end;
end;

Then you can call TIdTCPClient.SendCmd() afterwards as needed.

Upvotes: 1

Related Questions