tcpclient doesn't know about lost connection

K

Keith Langer

I have a tcpclient which is created from a tcplistener. Once the
connection is created, I issue a GetStream.Read with a ReceiveTimeout
of 0. This causes the thread to block until either data is received
or an exception is thrown.

Under normal circumstances, when the requester closes the connection I
would expect a System.IO.IOException. When the requester's process is
terminated abruptly, I get a System.InvalidOperationException. Either
way the Read operation stops blocking when the connection is closed.

Today I found one case where the tcpclient has no clue that the
connection was broken. If I connect via a VPN tunnel and then break
the VPN connection, the tcpclient continues to block on the Read
operation and an exception never occurs. I've waited up to five
minutes and still no exception. Now I have a thread that is blocking
forever on a non-existent connection! This lead me to have to
rearchitect the application to use a specific timeout and also abort
the connection if no data is received within a specific period of
time. I also found that when the program is shut down the thread will
not abort properly if it has issued a blocking Read operation. I've
tried issuing a Close and setting the tcplistener to nothing, but to
no avail.

Is there a way to block on the Read operation but still get an
exception when a socket is improperly closed?

thanks,
Keith
 
W

William Stacey [MVP]

1) Expect a certain message return and throw if not.
2) Set a timer and throw exception if no receive within your timeout.

Same issue with native winsock tcp apps.
 
L

Luc E. Mistiaen

This is because the default keepalive timeout is set to the equivalent of 2
hours.

Create a registry REG_DWORD value

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters\KeepAl
iveTime

with a value lower than the default 7200000 (2 hours in millseconds).
Make also sure that KeepAliveInterval is lower than halve the above value.

/LM
 
J

John Saunders

Keith Langer said:
I have a tcpclient which is created from a tcplistener. Once the
connection is created, I issue a GetStream.Read with a ReceiveTimeout
of 0. This causes the thread to block until either data is received
or an exception is thrown.

Under normal circumstances, when the requester closes the connection I
would expect a System.IO.IOException. When the requester's process is
terminated abruptly, I get a System.InvalidOperationException. Either
way the Read operation stops blocking when the connection is closed.

Today I found one case where the tcpclient has no clue that the
connection was broken. If I connect via a VPN tunnel and then break
the VPN connection, the tcpclient continues to block on the Read
operation and an exception never occurs. I've waited up to five
minutes and still no exception. Now I have a thread that is blocking
forever on a non-existent connection! This lead me to have to
rearchitect the application to use a specific timeout and also abort
the connection if no data is received within a specific period of
time. I also found that when the program is shut down the thread will
not abort properly if it has issued a blocking Read operation. I've
tried issuing a Close and setting the tcplistener to nothing, but to
no avail.

Is there a way to block on the Read operation but still get an
exception when a socket is improperly closed?

A connection is open iff it is open from both sides. It is possible for one
side of a connection to no longer be open without the other side being
informed. Consider what happens if the host the requester is running on is
simply powered off.

In order to detect this condition, you should consider using a periodic
"ping" message. If your side cannot deliver the message, an exception should
be thrown. You can go further by requiring the recipient of a ping message
to respond to it. This will not only tell you whether the TCP/IP endpoint is
still alive, but whether the code on the other side of that endpoint is
still alive, which may be a different thing. This technique can detect the
case of the requester going into an infinite loop, for instance.
 

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

Top