Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Oct : Re: Best method of keep-alive?
| Subject: | Re: Best method of keep-alive? |
| Posted by: | "Jamie Dale" (j.da..@turboz.net) |
| Date: | Mon, 2 Oct 2006 23:26:30 |
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:45217a36$1@newsgroups.borland.com...
>
> "Jamie Dale" <j.dale@turboz.net> wrote in message
> news:4521516d@newsgroups.borland.com...
>
>> I was wondering if anyone has a idea or method for implementing a
>> keep-alie system using TIdTCPClient and TIdTCPServer?
>
> 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 - Couldn't find anything about Indy there :(
> Or go to
> Indy's own newsgroups on the news://news.atozed.com server and browse
> through the old messages that are still on the server (there are no
> archives
> for Indy's server).
Sure thing.... Not found anything yet, but I'll keep looking!
>> I'm pretty familiar with the general theory - One end can send a 'ping'
>> and the other replies with a 'pong'.
>
> Yes, that is one way to do it.
Glad I got something right ;)
>> My question is what is the best way to do this
>
> There is no "best" way to implement it. It is whatever you are
> comfortable
> with, and what fits into your actual protocol.
Ok that makes me feel a little more confident
>> how can one end of the connection recognise if the time for
>> the reply has expired?
>
> It is each side's responsibility to keep track of how much time has
> elapsed
> between packets. In general, you need to take advance of the connection's
> ReadTimeout property to know when no data has arrived for a given period
> of
> time.
Ok, so I can just adjust my Athread.Connecdtion.ReadLn
TO: AThread.Connection.ReadLn(', 60) ???
This is my current OnExecute Method:
procedure TDefaultServer.IdTCPServer1Execute(AThread: TIdPeerThread);
//Things to do when server executed: EG something recv'd
var
Command: String;
begin
//Read Command/Message when it arrives
Command := AThread.Connection.ReadLn;
//If Command/Message is not blank and contains '¦' character
If (Command <> '') and (Pos('¦', Command) <> 0) then
begin
//Process Commands
CommandEngine.ProcessCmd(Command, AThread);
end;
end;
Can I instead simply do this?:
procedure TDefaultServer.IdTCPServer1Execute(AThread: TIdPeerThread);
//Things to do when server executed: EG something recv'd
var
Command: String;
begin
//Read Command/Message when it arrives
Command := AThread.Connection.ReadLn('', 60);
//If Command/Message is not blank and contains '¦' character
If (Command <> '') and (Pos('¦', Command) <> 0) then
begin
//Process Commands
CommandEngine.ProcessCmd(Command, AThread);
end;
If UpperCase(Command) = 'PING' then
begin
AThread.Connection.WriteLn('Pong');
end
else
If Command = '' then
begin
AThread.Connection.Disconnect;
end;
end;
>> 1) Server sends 'ping' with a serial number - IE Ping := 'ping:123';
>
> The client should be the one to send the pings, not the server.
Ok..
> This way,
> the client is actively telling the server that it wishes to remain
> connected
> to the server. If the server does not receive the ping for a given period
> of time, it can close the connection.
Ok..
> If the server were the one to send
> the pings, then it does not work as well.
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? -
Maybe a sloppy way of doing it but I thought it should work ;)
> Also, you don't need serial numbers in the pings at all, since the server
> would only be interested in knowing that data is still flowing through the
> connection in general, not necessarily what the data actually is.
Very good point!... My thought was to use the serials to basically keep
track of what pings had received a reply....
>> Client does not respond. Timer kicks in and checks array for replies
>> that are outstanding and increments a count.
>
> Since Indy servers are multi-threaded to begin with, there is no need for
> a
> ping array. Each individual thread can manage its own ping locally.
Ok still not sure exactly how to deal with that but I'm hoping the code
above will work!
>> Server then sends the same ping/serial again.
>
> If a ping is not replied to in a timely manner, the ping should not be
> attempted again. Simply disconnect the connection immediately. The
> client
> can then reconnect to the server if it wishes to.
But supposing soem sort of accidental error has happened (god knows what)...
if you don't give the client a 2nd chance then it could be wrongly
disconnected. 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). How would I deal with this?
Remy, as always, Thanks for your expert help.