views:

450

answers:

2

I'm wondering if in my Async Sockets in c#, receiving 0 bytes in the EndRead call means the server has actually disconnected us?

Many Examples I see suggest that this is the case, but I'm receiving disconnects a lot more frequent that I would be expecting.

Is this code correct? Or does endResult <= 0 not really mean anything about the connection state?

private void socket_EndRead(IAsyncResult asyncResult)
{ 
  //Get the socket from the result state
  Socket socket = asyncResult.AsyncState as Socket;

  //End the read
  int endResult = Socket.EndRead(asyncResult);

  if (endResult > 0)
  {
    //Do something with the data here


  }
  else
  {
    //Server closed connection?  
  }
}
+5  A: 

From the docs:

If the remote host shuts down the Socket connection and all available data has been received, the EndRead method completes immediately and returns zero bytes.

So yes, zero bytes indicates a remote close.

Mark Rushakoff
Well, the way MSDN words it, does not explicitly implicate that if 0 bytes are received, the connection must be closed, only that if the connection is closed, then 0 bytes will be received. Maybe I'm reading too far into the logic of this statement...
Redth
It's a blocking read. This means it will wait *forever* until one or more bytes come in. If you see zero bytes, the only possible situation was that the remote host closed the socket.
Mark Rushakoff
+1  A: 

0 read length should mean gracefull shutdown. Disconnect throws error (10054, 10053 or 10051).

In practice though I did notice reads complete with 0 length even though the connection was alive, and the only way to handle is to check the socket status on 0 length reads. The situation was as follows: post multiple buffers on a socket for receive. The thread that posted then is trimmed by the pool. The OS notices that the thread that made the requests is gone and it notifies the posted operations with error 995 ERROR_OPERATION_ABORTED, as documented. However what I've found is that when multiple operations are posted (ie. multiple Reads) only the first is notified with error 995, the subsequent are notified with success and 0 length.

Remus Rusanu
I added a comment to my question... So, would using SslStream.CanRead whenever I get a 0 length EndRead be adequate do you think?
Redth
If you have an encrypted stream on *top* of the network stream thinks are very different. First, you cannot have the situation I'm describing because SslStream will not accept multiple posted Reads. Second, even *if* the socket is returning success with 0 in error, the SslStream has already seen this and acted upon (ie. your Ssl state will now allow you to continue) so you have only one possible action, to dispose the stream and connect again.
Remus Rusanu
typos galore: thinks=>things, will now allow=> will *not* allow
Remus Rusanu
So, bottom line, if I'm getting int lengthRead = sslStream.EndRead(state) returning 0, I've pretty much got to suck it up and reconnect no matter what?
Redth
I suspect so. But I never tried this with encrypted streams, so is worth you give a shot. Maybe CanRead works... I'd be surprised though.
Remus Rusanu