How to receive text from Server to Client in Indy 10 TCP/IP in Delphi 7?

125 Views Asked by At

I am working on a chat application with Indy 10 in Delphi 7. Now, on the client side, Indy does not have an OnDataReceived or OnRead event, so how can I receive text from the server to the client?

I did try to use the OnWork event with a timer, but my timer is not woking.

Here are the codes for OnWork and TTimer that I used:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if zb_FDataReceived then
  begin
    ShowMessage('Timer triggered!');
    ClientOutput.Lines.Add('Server: ' + zb_FReceivedData);
    zb_FDataReceived := False;
  end;
end;

procedure TForm1.IdTime1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Integer);
begin
  if zb_FDataReceived then
  begin
    ShowMessage('Timer triggered!');
    ClientOutput .Lines.Add('Server: ' + zb_FReceivedData);
    zb_FDataReceived := False;
  end;
end;
1

There are 1 best solutions below

0
Remy Lebeau On

Most Indy clients operate synchronously, which is why there is no event in TIdTCPClient when incoming data arrives. The client doesn't read data from the socket until you tell it to read. The OnWork events are meant to be used for status reporting while you are reading/writing data, ie to update a progress bar, etc.

So, to do what you are attempting, you can use a timer, but not in the way you are trying to. On each timer event, you would need to query the socket with a short timeout to see if it has data waiting, and if so then read it. For example:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(0);
    Client.IOHandler.CheckForDisconnect;
    if Client.IOHandler.InputBufferIsEmpty then Exit;
  end;
  // read a message from the Client as needed...
end;

That being said, it is usually best to use a separate thread rather than a timer. Have the thread run a loop where each iteration reads from the socket until a new message arrives and then notifies the Main UI thread to display the message. For example:

type
  TReadingThread = class(TThread)
  protected
    FClient: TIdTCPClient;
    procedure Execute; override;
  public
    constructor Create(AClient: TIdTCPClient);
  end;

constructor Create(AClient: TIdTCPClient);
begin
  inherited Create(False);
  FClient := AClient;
end;

procedure TReadingThread.Execute;
begin
  while (not Terminated) and FClient.Connected do
  begin
    // read a message from FClient as needed...
    // update main UI as needed ...
  end;
end;
Client.Connect;
RThread := TReadingThread.Create(Client);
...
Client.Disconnect;
RThread.Terminate;
RThread.WaitFor;
RThread.Free;