Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Oct : Re: Best method of keep-alive?

www.cryer.info
Managed Newsgroup Archive

Re: Best method of keep-alive?

Subject:Re: Best method of keep-alive?
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Mon, 2 Oct 2006 17:11:56

"Jamie Dale" <j.dale@turboz.net> wrote in message
news:45219211@newsgroups.borland.com...

> > This has been discussed many many times before.  Please go to
> > http://www.deja.com and search through the newsgroup archives.
>
> Goes to groups.google.com

Yes, Google bought out Deja several years ago.  Google maintains the
archives now.  They are fully intact, going back almost 10 years.

> Couldn't find anything about Indy there  :(

Then you did not do a very detailed search, because there are TONS of
Indy-related and socket-related questions in the Borland archives.  For
example:


http://groups.google.com/groups?lnk=hpsg&q=socket+keep+alive+group%3A*delphi*


http://groups.google.com/groups/search?q=indy+keep+alive+group%3A*delphi*

Learn to use the Advanced search options.  They are very flexible and very
useful.

> Ok, so I can just adjust my Athread.Connecdtion.ReadLn
> TO: AThread.Connection.ReadLn(', 60)   ???

60 milliseconds is much too short a time.  TCP latency could easily be
longer than that without losing the connection.  I would suggest using 30
seconds minumum.  Even better, use a 1 minute timout and then have the
client send the ping every 30 seconds to ensure at least 1 ping makes it
through to the server during the 1 minute window.

With that said, yes you can use the ATimeout parameter to ReadLn(), or you
can use the ReadTimeout property on the TIdTCPConnection object itself.
Either way, just be sure to look at the ReadLnTimedOut property after
ReadLn() exits.

> This is my current OnExecute Method:

Try this code:

    procedure TDefaultServer.IdTCPServer1Execute(AThread: TIdPeerThread);
    var
        Command: String;
    begin
        Command := AThread.Connection.ReadLn('', 60000);
        if AThread.Connection.ReadLnTimedOut then
        begin
            AThread.Connection.DisconnectSocket;
            Exit;
        end;
        if AnsiSameText(Command, 'PING') then
        begin
            AThread.Connection.WriteLn('PONG');
            Exit;
        end;
        if Pos('|', Command) <> 0 then
        begin
            // process command...
            CommandEngine.ProcessCmd(Command, AThread);
        end else
        begin
            // do something else ...
        end;
    end;

> Why? - I was assuming it could be done by using a TTimer and
> simply going through an array of AThreads and sending a 'ping' to
> their connection? -

That would require much more work to implement on the server side.  You
would have to synchronize all of your writes to each client connection to
ensure that the timer's pings do not overlap any responses that the threads
happen to be writing at the same time, thus corrupting everything.  It is a
lot easier to just have the server be a passive responder to the client's
pings instead of an active pusher of its own pings, and handle the ping
replies in the same thread that receives them.

> My thought was to use the serials to basically keep track of what
> pings had received a reply....

Completely unnecessary.

> But supposing soem sort of accidental error has happened (god knows
what)...

Doesn't matter.  If the client sends a ping and it takes a long time for the
reply to arrive, then the client should disconnect and reconnect after the
ping has timed out.  That is the whole point of implementing a kepp alive to
begin with - to detect when the connection is too slow, or has been lost
altogether.

> if you don't give the client a 2nd chance then it could be wrongly
> disconnected.

All the more reason that the pings should be sent by each client
individually instead of the server.  If a client does not send any data to
the server in a timely manner, then the server can drop the connection with
that client and release resources that could be used for other things.  This
is also the only way the server can detect clients being lost.  If the
client is too slow, then tough.  The client has the responsibility to
send/receive data as fast as it can, and to not block the communications
unnecessarily.

EG 56k modem utilising full bandwidth could block a ping

> Or sending a file down the very same connection would make
> it unusable for a while (until the file has finished).

No, it wouldn't.  There are ways to multiplex multiple channels of
communication over a single connection.  Although that is not really needed,
since the presense of a file transfer on a connection is enough to act as
that connection's keep-alive by itself.  The whole point of keep-alives is
to make sure data is transferrable across the data.  The only reason to
introduce 'ping'-style commands into the protocol is to deal with idle
periods of inactivity from wrongs closing the connection between actual
operations.


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive