Detecting Disconnect on TCP Socket

B

Bruce Vander Werf

I am using the asynchronous send/receive methods of the Socket class.

When the remote end closes the socket, the callback for receive is
called and EndReceive returns 0.

Socket.Connected still returns true at this point, which I know is
expected behavior, so when I reach this state, I begin sending on this
socket every few seconds until an error is generated.

After the exception is raised, Socket.Connected returns false.
However, I cannot connect again to this socket. Calls to BeginConnect
fail with a message "A connect request was made on an already
connected socket."

How do I work around this, short of recreating the socket?

--Bruce
 
D

David Sworder

Bruce Vander Werf said:
I am using the asynchronous send/receive methods of the Socket class.

When the remote end closes the socket, the callback for receive is
called and EndReceive returns 0.

Did you immediately call Close() against the socket at this point? If
not, this might be your problem. Don't bother trying to send stuff across
this socket after EndReceive() has returned zero. It's like beating a dead
horse (that's just an expression).

If I were you, I'd then call Dispose() on the socket, stop referencing
it, and let the GC get rid of it. Next time you need to initiate/accept a
new connection, just use a new Socket object. I know you said you were
against the idea of creating a new socket, but hey, why not?
 
D

David Sworder

Hi Alex,
it's not always like this. I've seen situations when endreceive delivered 0
bytes, however beginreceive issued at that point was getting more data. It
really depends on how remote end behaves. If remote server is slow - you can
get 0 bytes while there are data available.

Are you sure about this? I just double-checked the documentation for
EndReceive() and it looks like a return value of 0 indicates that the remote
system has Shutdown the connection.

Consider an example where a client connects to a server and doesn't send
any data for five minutes. The server calls BeginReceive() immediately after
the connection is accepted. The first callback won't be even be made for 5
minutes. When the callback is finally made, there will be at least 1 byte of
data to receive. In other words, EndReceive() should return a value greater
than zero. If for some reason the client terminates early (say after two
minutes), the callback will be made and the server's EndReceive() call will
return zero. At that point, are you saying that it's possible for further
data to be in the pipeline? I wouldn't have thought that this is the case
since the socket is already shutdown. I would think that the socket should
immediately be closed and disposed at this point.
If you know what you should get from remote server you can check if you got
everything, for example using end-of-file byte or some tag line. I've seen
situations when I was receiving 5-10MB in chunks of 100-200K with delays of
several seconds between chunks.

...but your EndReceive() should never have returned zero between chunks,
right? If it did, wouldn't this imply that the client had dropped the
connection?

David
 
D

David Sworder

aha! Thanks for the clarification.

AlexS said:
David,

MSDN says only:

-quote-
"If the remote host shuts down the Socket connection with the Shutdown
method, and all available data has been received, the EndReceive method will
complete immediately and return zero bytes"
-unquote-

It says nothing about 0 bytes meaning always shutdown with complete receipt.
It really depends on server on remote end. 0 could mean shutdown, lack of
data, not available data and other things, but not always shutdown.

HTH
Alex


data. byte
 
A

AlexS

Hi, Bruce

This is normal. After exception you usually can't use same socket. You have
to close/destroy old one and create new. I mean of course network-related
exception, not division by zero :)

HTH
Alex
 
A

AlexS

David,

it's not always like this. I've seen situations when endreceive delivered 0
bytes, however beginreceive issued at that point was getting more data. It
really depends on how remote end behaves. If remote server is slow - you can
get 0 bytes while there are data available.
If you know what you should get from remote server you can check if you got
everything, for example using end-of-file byte or some tag line. I've seen
situations when I was receiving 5-10MB in chunks of 100-200K with delays of
several seconds between chunks. Until exception happens or
socket.Connected!=true socket could be considered as working and connected.

HTH
Alex
 
A

AlexS

David,

MSDN says only:

-quote-
"If the remote host shuts down the Socket connection with the Shutdown
method, and all available data has been received, the EndReceive method will
complete immediately and return zero bytes"
-unquote-

It says nothing about 0 bytes meaning always shutdown with complete receipt.
It really depends on server on remote end. 0 could mean shutdown, lack of
data, not available data and other things, but not always shutdown.

HTH
Alex
 

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