5

I have a webserver application developed using idHttpServer. When a client connects do my webserver and, for some unknown reason, got disconnect (not a gracefully disconnect) my webserver does not get notified. I know this is the normal behavior but I need to know when the client dies.

There are a few ways of doing this. I know 2 good ways:

1 - Implement a heart beat mechanism. The client socket notifies the server that it is still alive (need some work and some code to make it works)

2 - TCP Keep Alive. This is the way I like most because it requires not too much code and work. But I got a few questions regarding this.

  • Is this possible to be used with idHttpServer (for the server) and wininet functions (for the client)?
  • Does that really works as expected? I mean, the server gets notfied when the client dies all the times?
  • Does anyone have a sample of setting this on wininet? (I guess this must be set on the client side, right?)
  • Is there a better way of notify a server that the client is dead (using indy and wininet, of course)

EDIT

I am using Delphi 2010 and last Indy10 source code from their svn.

Rafael Colucci
  • 6,018
  • 4
  • 52
  • 121

1 Answers1

4

If you are using an up-to-date Indy 10 release, then you can use the TIdSocketHandle.SetKeepAliveValues() method:

procedure SetKeepAliveValues(const AEnabled: Boolean; const ATimeMS, AInterval: Integer);

For example:

procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext);
begin
  // send a keep-alive every 1 second after
  // 5 seconds of inactivity has been detected
  AContext.Binding.SetKeepAliveValues(True, 5000, 1000);
end;

Note that the ATimeMS and AInterval parameters are only supported on Win2K and later.

Otherwise, use the TIdSocketHandle.SetSockOpt() method directly to enable the TCP/IP SO_KEEPALIVE option manually:

procedure TIdSocketHandle.SetSockOpt(ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; AOptVal: Integer);

For example:

procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext);
begin
  AContext.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_KEEPALIVE, 1);
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • By doing this, indy should call the OnDisconnect event? If so, this is not working. If I unplug the network cable idHttpServer does not call OnDisconnect event. – Rafael Colucci May 05 '11 at 13:03
  • 1
    `OnDisconnect` is not fired until the socket's owning thread is stopped. Until the OS reports errors on the socket, Indy has no way of knowing it is a dead connection. Not all OS versions recognize cable pulls as lost connections right away, so even with keepalives enabled, several keepalives have to elapse before the OS finally stops trying. That takes time. Then it starts reporting errors on the socket, which Indy can detect and raise exceptions for the next time the socket is accessed. Make sure you are not swallowing Indy's exceptions in your code, let he server handle them. – Remy Lebeau May 06 '11 at 08:11