Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TIDTcpServer Disconnect Question

2 views
Skip to first unread message

Randy Vose

unread,
Sep 17, 2001, 7:39:54 PM9/17/01
to
Hi All ...

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


Fons Seesink

unread,
Sep 18, 2001, 4:41:50 AM9/18/01
to
About the same problem here

hoping for the answer

Fons Seesink
Actisoft

"Randy Vose" <rjv...@earthlink.net> schreef in bericht
news:3BA689CA...@earthlink.net...

Doychin Bondzhev - Team Indy

unread,
Sep 18, 2001, 5:00:21 AM9/18/01
to
Can you post some sample code that I can use to show you how to deal with
this?

--
------------------------------
Doychin Bondzhev - Team Indy
doy...@dsoft-bg.com

"Randy Vose" <rjv...@earthlink.net> wrote in message
news:3BA689CA...@earthlink.net...

Ernst Gerlach

unread,
Sep 18, 2001, 10:12:04 AM9/18/01
to

"Randy Vose" <rjv...@earthlink.net> schrieb im Newsbeitrag
news:3BA689CA...@earthlink.net...

> Hi All ...
>
> 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.
>
---snip---
Its a problem of tcp/ip. If you design your own protocol, you have to
implement:
a) a "QUIT" command
b) a "NOOP" (no operation) command
c) a time out counter in AThread.Data

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


Martin James

unread,
Sep 18, 2001, 8:00:07 AM9/18/01
to

Randy Vose <rjv...@earthlink.net> wrote in message
news:3BA689CA...@earthlink.net...
> Hi All ...
>
> 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.

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!


Randy Vose

unread,
Sep 18, 2001, 8:55:46 PM9/18/01
to
Thanks for the reply ....

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

Randy Vose

unread,
Sep 18, 2001, 8:51:42 PM9/18/01
to
Thanks for the reply. All I'm doing on the client is calling the Disconnect
method as follows:

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

Randy Vose

unread,
Sep 18, 2001, 9:06:10 PM9/18/01
to
Thanks for the reply! I'm thinking about implementing a QUIT or LOGOFF protocol
as you suggest. On the client, I'd do exactly what you have below, but on the
server, I'd do something like:

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

Doychin Bondzhev - Team Indy

unread,
Sep 19, 2001, 2:16:36 AM9/19/01
to
In order to recevive signel from the socket you have to check his state
periodically. WIthout calling winsock you have no way to find that the
socket is closed.

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...

0 new messages