Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indy TCPClient OnDisconnect event not working

type
  TForm8 = class(TForm)
    idtcpclnt1: TIdTCPClient;
    idtcpsrvr1: TIdTCPServer;
    procedure FormCreate(Sender: TObject);
    procedure idtcpsrvr1Execute(AContext: TIdContext);
    procedure idtcpclnt1Disconnected(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form8: TForm8;

implementation

{$R *.dfm}

procedure TForm8.FormCreate(Sender: TObject);
begin
  idtcpclnt1.Connect;
end;

procedure TForm8.idtcpsrvr1Execute(AContext: TIdContext);
begin
  AContext.Connection.Disconnect(true); //this gets called
end;

procedure TForm8.idtcpclnt1Disconnected(Sender: TObject);
begin
  ShowMessage('true'); //but this does not
end;

The OnDC never gets handled. Why?

like image 407
netboy Avatar asked Oct 17 '25 19:10

netboy


2 Answers

Indy client components are not event-driven (with a couple of exceptions, such as TIdTelnet). The TIdTCPClient.OnDisconnect event is NOT triggered when the server disconnnects on its end, like you are assuming. This is by design. TIdTCPClient will not know about the disconnection until it tries to access the socket again, at which time it will raise an exception, such as EIdConnClosedGracefully. The TIdTCPClient.OnDisconnect event is only triggered when the TIdTCPClient.Disconnect() method is called on the client side, which you are not doing.

In order to detect server-side disconnects with TIdTCPClient, you have to read from the socket periodically, such as in a timer or a separate thread.

like image 146
Remy Lebeau Avatar answered Oct 20 '25 14:10

Remy Lebeau


Ok, my mistake. You code does not work, but that is correct. Let me explain why:

The AContext.Connection.Disconnect(true) method calls DisconnectNotifyPeer wich is not implemented in TCPServer. Why? Because it should not.

When you disconnect in the server, what indy does is invalidate the socket and close it. The client will only notice that the server disconnected when it tries to send some request. And you code does not do that. This is a default behavior of indy.

In order to notify the client that the server disconnected, indy and any other suites should implement what we call heartbeat. Heartbeat is a technique that from time to time tries to send small packets to an socket in order to detect that it is still alive. The only way of detect a socket disconnection is trying to write something in that socket. Google about heartbeat and you will understand what I mean.

EDIT

Check this out.

like image 31
Rafael Colucci Avatar answered Oct 20 '25 15:10

Rafael Colucci



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!