[Socket] detecting the (brute) disconnection of a client

  • Thread starter Thread starter timor.super
  • Start date Start date
T

timor.super

Hi group,

I've written a client/server application, using the dotnet sockets.
In my server, I have a thread waiting for messages with :

ret = currSocket.Receive(buffer, 1024, SocketFlags.None);

When the client exits, I close the socket with a specific message
(like "end") and the thread terminate in a proper manner, but If my
client crashes, the server is still waiting for receiving data, and
the thread is blocked.

How can I detect that the client is out ? (then, if I can detect it,
maybe I can terminate the thread brutally (or if there's a better
way ...))

Thanks for your help,

N.
 
[...]
When the client exits, I close the socket with a specific message
(like "end") and the thread terminate in a proper manner, but If my
client crashes, the server is still waiting for receiving data, and
the thread is blocked.

How can I detect that the client is out ? (then, if I can detect it,
maybe I can terminate the thread brutally (or if there's a better
way ...))

Generally (as you've found) TCP/IP won't detect a broken connection until
the detecting end attempts some actual i/o. That is, tries to send and
fails. If only receiving, it will sit and continue to try to receive
indefinitely. This allows TCP/IP to be able to transparently deal with
the situation where both endpoints are fine, but something in between is
temporarily interrupted.

The two usual approaches are to either implement a timeout (when the
receiver knows it should receive some data within a certain amount of
time), or provides a mechanism for the user to interrupt the receiver (at
which point it would simply close the socket). Sometimes these are both
used.

Pete
 
Peter Duniho a écrit :
[...]
When the client exits, I close the socket with a specific message
(like "end") and the thread terminate in a proper manner, but If my
client crashes, the server is still waiting for receiving data, and
the thread is blocked.

How can I detect that the client is out ? (then, if I can detect it,
maybe I can terminate the thread brutally (or if there's a better
way ...))

Generally (as you've found) TCP/IP won't detect a broken connection until
the detecting end attempts some actual i/o. That is, tries to send and
fails. If only receiving, it will sit and continue to try to receive
indefinitely. This allows TCP/IP to be able to transparently deal with
the situation where both endpoints are fine, but something in between is
temporarily interrupted.

The two usual approaches are to either implement a timeout (when the
receiver knows it should receive some data within a certain amount of
time), or provides a mechanism for the user to interrupt the receiver (at
which point it would simply close the socket). Sometimes these are both
used.

Pete

Thanks for your answer,

so i think i have to try to send something to the client that has
crashed, and if an exception occurs, then the client is deconnected.

Or maybe, i have to use the timeout, the if timed out, i try to send
something to check if the client is still here

do you think it is a good idea ?

Should I use the SendTimeout property with the Send() method ?
 
Hi,

Hi group,

I've written a client/server application, using the dotnet sockets.
In my server, I have a thread waiting for messages with :

ret = currSocket.Receive(buffer, 1024, SocketFlags.None);

When the client exits, I close the socket with a specific message
(like "end") and the thread terminate in a proper manner, but If my
client crashes, the server is still waiting for receiving data, and
the thread is blocked.

How can I detect that the client is out ? (then, if I can detect it,
maybe I can terminate the thread brutally (or if there's a better
way ...))

You cannot, y ou have to be ready to receive an IO exception.
 
[...]
so i think i have to try to send something to the client that has
crashed, and if an exception occurs, then the client is deconnected.

That would be one way to detect the situation, yes.
Or maybe, i have to use the timeout, the if timed out, i try to send
something to check if the client is still here

You can either use the timeout itself as an indication of connection
failure, or you can attempt to send data after the timeout. Either one
will work, and which one you want depends on your needs.
do you think it is a good idea ?

Not really. I mean, I don't know your particular situation but it's my
opinion that enforcing a failure for no immediate need or reason isn't
useful.

The server has no way to know if the connection has failed due to a
client-side crash, or simply due to a temporary problem with the network.
A temporary problem may resolve itself and so detecting that condition is
pointless and results in unnecessarily closing the connection.

IMHO, it would be better to simply let the server continue to assume that
the connection is valid unless there is some explicit, non-arbitrary
verification that it's not. This could include:

* The server actually needs to send data to the client and the error
is detected at that time
* The server receives a second connection request from the same client
(detected by IP address or by some unique client ID, such as a username
and/or password)
* Someone with access to the server (by whatever mechanism you
choose...could be a remote control interface, or simply a button on the UI
of the server on the same computer it's running on) explicitly closes the
connection

If you are concerned about the connection remaining open and consuming
resources that are needed for other valid connections, then you could
simply wait until such time as you need those resources (eg you get an
exception creating a socket or accepting a connection) and then close
existing connections that have been idle the longest, and idle for some
reasonable minimum amount of time (what time is "reasonable" depends
entirely on your needs).
Should I use the SendTimeout property with the Send() method ?

It seems to me that if it's the receive you want to apply the timeout to,
then it's the ReceiveTimeout property you want to set.

I don't know how the .NET Socket implementation of ReceiveTimeout works,
but if it's the same as the regular Winsock note that if and when the
socket times out, it is no longer usable. So, if you want to send data
after the timeout, you need to implement the timeout some other way (using
a timer, for example).

In other words:

* If you are simply going to close the socket after the timeout
occurs, use ReceiveTimeout
* If you are going to query the other endpoint to see if they are
still connected after the timeout, use your own timer and then when it
expires do the send. Of course, if the other end replies, your receive
will complete and you'll have to initiate it again to wait for real data.

If you are doing the latter, you may find that using SetSocketOption with
the KeepAlive option is preferable. Though, I don't see any way in .NET
to change the keep-alive interval, so if the default of 2 hours isn't
appropriate for your situation, you may have to implement the timeout
manually as above.

Of course, keep in mind my comments about. This timeout stuff may or may
not be the correct way to address the issue. As I said, I don't
personally think that arbitrarily timing out a connection is necessarily
the right thing to do. There are other ways to address the situation of a
crashed client...there are situations in which timeouts make sense, but
because of the chance of a false positive with timeouts, they should only
be used when you really want a timeout specifically, rather than when you
are trying to address some other issue.

Pete
 
[...]
so i think i have to try to send something to the client that has
crashed, and if an exception occurs, then the client is deconnected.

That would be one way to detect the situation, yes.
Or maybe, i have to use the timeout, the if timed out, i try to send
something to check if the client is still here

You can either use the timeout itself as an indication of connection
failure, or you can attempt to send data after the timeout. Either one
will work, and which one you want depends on your needs.
do you think it is a good idea ?

Not really. I mean, I don't know your particular situation but it's my
opinion that enforcing a failure for no immediate need or reason isn't
useful.

The server has no way to know if the connection has failed due to a
client-side crash, or simply due to a temporary problem with the network.
A temporary problem may resolve itself and so detecting that condition is
pointless and results in unnecessarily closing the connection.

IMHO, it would be better to simply let the server continue to assume that
the connection is valid unless there is some explicit, non-arbitrary
verification that it's not. This could include:

* The server actually needs to send data to the client and the error
is detected at that time
* The server receives a second connection request from the same client
(detected by IP address or by some unique client ID, such as a username
and/or password)
* Someone with access to the server (by whatever mechanism you
choose...could be a remote control interface, or simply a button on the UI
of the server on the same computer it's running on) explicitly closes the
connection

If you are concerned about the connection remaining open and consuming
resources that are needed for other valid connections, then you could
simply wait until such time as you need those resources (eg you get an
exception creating a socket or accepting a connection) and then close
existing connections that have been idle the longest, and idle for some
reasonable minimum amount of time (what time is "reasonable" depends
entirely on your needs).
Should I use the SendTimeout property with the Send() method ?

It seems to me that if it's the receive you want to apply the timeout to,
then it's the ReceiveTimeout property you want to set.

I don't know how the .NET Socket implementation of ReceiveTimeout works,
but if it's the same as the regular Winsock note that if and when the
socket times out, it is no longer usable. So, if you want to send data
after the timeout, you need to implement the timeout some other way (using
a timer, for example).

In other words:

* If you are simply going to close the socket after the timeout
occurs, use ReceiveTimeout
* If you are going to query the other endpoint to see if they are
still connected after the timeout, use your own timer and then when it
expires do the send. Of course, if the other end replies, your receive
will complete and you'll have to initiate it again to wait for real data.

If you are doing the latter, you may find that using SetSocketOption with
the KeepAlive option is preferable. Though, I don't see any way in .NET
to change the keep-alive interval, so if the default of 2 hours isn't
appropriate for your situation, you may have to implement the timeout
manually as above.

Of course, keep in mind my comments about. This timeout stuff may or may
not be the correct way to address the issue. As I said, I don't
personally think that arbitrarily timing out a connection is necessarily
the right thing to do. There are other ways to address the situation of a
crashed client...there are situations in which timeouts make sense, but
because of the chance of a false positive with timeouts, they should only
be used when you really want a timeout specifically, rather than when you
are trying to address some other issue.

Pete

Thanks for your answer, I will try all o see what fits the better for
my problem

Can I consider that 30 secs is enough to say that a connection is
lost ?

Best regards,

Nico ...
 
How can I detect that the client is out ? (then, if I can detect it,
maybe I can terminate the thread brutally (or if there's a better
way ...))

You must try to send something to client, there is no other way.
Usually it is solved by implementing KeepAlive message every while.
This is also important because, for example, Windows could kill an
active connection when there was no traffic for some time.
 
[...]
Can I consider that 30 secs is enough to say that a connection is
lost ?

Impossible for me to say. Impossible for anyone but you to say, really.
It just depends on the nature of the protocol you're implementing and
whether it should never go 30 seconds without seeing any date or not.
Keeping in mind, of course, that temporary interruptions in the connection
may slow things down beyond what normal gaps in the data would be. So if
you normally would see 30 second gaps, then the timeout needs to be
something larger than that.

There are lots of reasons that it's better to use some other mechanism
than a timeout. One of them is that it can be difficult to know in
advance what a suitable timeout value is.

Pete
 
You must try to send something to client, there is no other way.
Usually it is solved by implementing KeepAlive message every while.
This is also important because, for example, Windows could kill an
active connection when there was no traffic for some time.

Windows will not kill a connection. Your socket will remain valid and
connected for as long as your application leaves it open.

Pete
 
Windows will not kill a connection. Your socket will remain valid and
connected for as long as your application leaves it open.

Pete

ok
thanks for your answers,

that solves my problem

Best regards,

N.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top