tags:

views:

576

answers:

1

Hi

I'm writing a simple socket client which uses only one socket. So I figured I could reuse a single SocketAsyncEventArgs for all receive operations. It's working fine as long as the socket is connected. When the server disconnects, the client will enter a infinite receive loop spamming "Receive Success" in the console.

Shouldn't e.SocketError != SocketError.Success be true when the socket is disconnected?

Here is part of the code:

private void Completed(object sender, SocketAsyncEventArgs e)
{
   if (e.SocketError != SocketError.Success)
      status = 0;

   System.Console.WriteLine(e.LastOperation + " " + e.SocketError);

   if (status == 1)
   {
      switch (e.LastOperation)
      {
         case SocketAsyncOperation.Connect:
            ProcessConnect(e);
            break;
         case SocketAsyncOperation.Receive:
            ProcessReceive(e);
            break;
         case SocketAsyncOperation.Send:
            ProcessSend(e);
            break;
         default:
            status = 0;
            break;
      }
   }

   if (status != 1)
      CloseSocket();
}

private void ProcessReceive(SocketAsyncEventArgs e)
{
   if (!socket.ReceiveAsync(e))
      Completed(null, e);
}
+1  A: 

If your socket is set up for a byte stream then you may get a callback with zero bytes, this indicates that a graceful closure of the socket has occurred and that no more bytes will ever be read. Simply check for this in your code, e.g.

private void ProcessReceive( SocketAsyncEventArgs e )
{
    AsyncUserToken token = e.UserToken as AsyncUserToken;
    if( e.ByteTransferred > 0 && e.SocketError == SocketError.Success )
    {
        // .. process normally ..
    }
    else
    {
        CloseClientSocket( e );
    }
}

private void CloseClientSocket( SocketAsyncEventArgs e )
{
    AsyncUserToken token = e.UserToken as AsyncUserToken;
    try
    {
        token.Socket.Shutdown( SocketShutdown.Send );
    }
    // throws error if it's already closed
    catch( Exception ) {}
    token.Socket.Close();
}

Of course you'll also need to stop your client from trying to use the socket, but I'm sure you can work that part out.

Timothy Walters
Thank you. That was a simple sulotion and it solved the problem :)
remdao
Perhaps you could 'tick' my answer as correct then? :)
Timothy Walters