I'm using Indy 8.0 with Delphi 6 and am seeing an intermittent problem which
may have more to do with WinSock than with Indy, but I thought I'd put it out
here to see if anyone has any input.
I have a dozen or so users connecting to a TIdTcpServer using a
TIdTcpClient-based app. Both client and server application work great, except
that in a few cases, when my clients properly disconnect, my server doesn't
receive a disconnect event and thus the server thread for that client remains
active. When the user restarts the client app and logs back in to my server,
the server creates a second connection thread or that same client. The end
result is that I end up with multiple threads in the server for a single
client, which wastes resources in the server app. The only way to clear out
the extra server threads is to shutdown and restart the server app.
I can put some code in the OnConnect handler of the server to check the active
connection threads to see if there is already a thread servicing the client IP
which is requesting the new connection, but I don't understand why the
disconnect message never makes it to my server when the client disconnected
originally. Again, this only happens with some of my clients. Other clients
connect and disconnect and the server recognizes it just fine.
The client machines are using NT 4, SP6. My server app is running under Win2k
Server, SP2.
I'm assuming that this might be a problem with the client machine config
(Winsock problem, perhaps?) as I could not find any posts on the web reporting
this kind of "missed" disconnect problem with TIdTcpServer.
Does anyone know why my server might not see a client disconnect, when the
clients are known to be properly disconnecting? Is there any other way in Indy
for a TidTcpCient to gracefully break a connection to a TidTcpServer?
Any info would be appreciated. Thanks!
--
Randy V.
rjv...@earthlink.net
hoping for the answer
Fons Seesink
Actisoft
"Randy Vose" <rjv...@earthlink.net> schreef in bericht
news:3BA689CA...@earthlink.net...
--
------------------------------
Doychin Bondzhev - Team Indy
doy...@dsoft-bg.com
"Randy Vose" <rjv...@earthlink.net> wrote in message
news:3BA689CA...@earthlink.net...
Client side, you say:
writeLn('QUIT'); //packed in a try ... except
if Connected then Disconnect;
Server side:
begin { ------------------- Execute ------------------- }
FData := Pointer(AThread.Data);
try
FData.BefehlsNummer := 0;
FData.CliPhase := 0;
FData.SerPhase := 0;
FData.TimeOutCount := 0; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
FData.Beenden := false; // Beenden = Stop (sorry of german
expressions)
AThread.Connection.WriteLn('START');
while AThread.Connection.Connected and (not FData.Beenden)
and (FData.TimeOutCount <= 60) do begin // <<< here you kick of the
connection, if there is no more traffic
FData.EmpfangString := AThread.Connection.ReadLn('', 1000); // timeout
is set to one second
if (not AThread.Connection.ReadLnTimedOut) then begin
FData.TimeOutCount := 0; // if getting Data, set the couter to
zero
ProcessFax; // <<< this is the sub procedure to handle the command.
end else FData.TimeOutCount := FData.TimeOutCount + 1;
end;
finally
if AThread.Connection.Connected
then AThread.Connection.Disconnect;
end;
end;
Client side, you a) make a centralized procedure to write over the socket
like:
procedure WriteToSocket(TheLine: string);
begin
MyClient.WriteLn(TheLine);
NoopCount := 0;
end;
b) set a timer:
OnTimerX
begin
inc(NoopCount);
if NoopCount > 5 then WriteToSocket('NOOP);
end;
hth Ernst
Yes, that is the correct behaviour. If, for example, the client just 'goes
away' without a managed disconnect, your session will remain up forever.
This is how TCP/IP works. If you need to prevent multiple connections, you
have to use some sort of protocol that involves polling & timeouts to detect
loss of link.
> I can put some code in the OnConnect handler of the server to check the
active
> connection threads to see if there is already a thread servicing the
client IP
> which is requesting the new connection, but I don't understand why the
> disconnect message never makes it to my server when the client
disconnected
> originally. Again, this only happens with some of my clients. Other
clients
> connect and disconnect and the server recognizes it just fine.
This scheme restricts your clients to one per node. This may, or may not,
be a problem for you.
> The client machines are using NT 4, SP6. My server app is running under
Win2k
> Server, SP2.
>
> I'm assuming that this might be a problem with the client machine config
> (Winsock problem, perhaps?) as I could not find any posts on the web
reporting
> this kind of "missed" disconnect problem with TIdTcpServer.
>
> Does anyone know why my server might not see a client disconnect, when the
> clients are known to be properly disconnecting?
Don't know!
I understand that if the connection drops unexpectedly that TCP/IP won't notice
unless some kind of keep-alive protocol is implemented. What I'm seeing with my
app is that the connection is being terminated properly by the client, yet the
server doesn't see the disconnect and thus takes no action to free the thread
associated with that connection.
Implementing something to check the current threads in the server to prevent a
client from logging in more than once isn't a problem for me, but it's something
I'd rather not do.
From reading some of the other responses, it looks like I will need to implement
a LOGOFF protocol to disconnect the client from the server side (or something
similar)>
Thanks again for the help!
--
Randy V.
rjv...@earthlink.net
procedure TViewerForm.FormClose(.....)
begin
if IndyTcpClient.Connected then
IndyTcpClient.Disconnect;
end;
On the server side, I have an OnDisconnect event handler to do some object
cleanup within the server. Within the OnDisconnect in the server, I do nothing
with AThread.Connection.
The primary problem is that when some of my clients execute the
IndyTcpClient.Disconnect method, the server never sees it. In reading some
other responses, it appears that I should be able to implement a LOGOFF or
similar protocol to close the connection on the server side.
Now that I'm looking at, is it possible the Connected property of the
IndyTcpClient is getting set to FALSE at some point? My users are not reporting
any error messages or ConenctionClosedGracefully errors and I assume if the
property changed from TRUE to FALSE that I'd trap it.
Thanks again for the reply.
--
Randy V.
rjv...@earthlink.net
TIdTcpServer.OnExecute(...)
var
sData: string;
begin
sData := IdTcpServer.ReadLn();
if sData := "QUIT" then
Athread.Connection.Disconnect;
end;
I do have a question about this implementation. If I explicitly call Disconnect
in the client, and also call Disconnect in the server, will this cause any
problems on either end? Will the server see two "disconnect" messages from the
same client?
Thanks again!
--
Randy V.
rjv...@earthlink.net
If you have something like this in OnExecute:
with ATHread.Connection do
repeat
s: =readln;
// Do your protocol stuff
until not Connected;
You will recevie exception when the connection is closed.
You have to decide which side will close the connection and whcih will do
this check.
There is Connection.CheckForDisconnect method which you can use to do the
same check as with ReadLn;
with AThread.Connection do
try
repeat
s: =readln;
// Do your protocol stuff
until not CheckForDisconnect(false);
finally
// Cleanup procedure
end;
--
------------------------------
Doychin Bondzhev - Team Indy
doy...@dsoft-bg.com
"Randy Vose" <rjv...@earthlink.net> wrote in message
news:3BA7EC1E...@earthlink.net...