views:

367

answers:

4

The Socket class has a method .AcceptAsync which either returns true or false.

I'd thought the false return value was an error condition, but in the samples Microsoft provide for Async sockets they call the callback function synchronously after checking for failure, as shown here:

public void StartAccept(SocketAsyncEventArgs acceptEventArg)
    {
        if (acceptEventArg == null)
        {
            acceptEventArg = new SocketAsyncEventArgs();
            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
        }
        else
        {
            // socket must be cleared since the context object is being reused
            acceptEventArg.AcceptSocket = null;
        }

        m_maxNumberAcceptedClients.WaitOne();
        bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
        if (!willRaiseEvent)
        {
            ProcessAccept(acceptEventArg);
        }
    }

    /// <summary>
    /// This method is the callback method associated with Socket.AcceptAsync operations and is invoked
    /// when an accept operation is complete
    /// </summary>
    void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
    {
        ProcessAccept(e);
    }

Why do they do this? It defeats the purpose of asynchronous sockets and stops the method from returning.

+2  A: 

From the AcceptAsync specifications:

Returns false if the I/O operation completed synchronously. The SocketAsyncEventArgs.Completed event on the e parameter will not be raised and the e object passed as a parameter may be examined immediately after the method call returns to retrieve the result of the operation.

When it returns false you're supposed to process immedeatly the newly accepted socket.

Remus Rusanu
A: 

As Remus says, when it returns false you process it syncronously rather than asynchronously.

Yes, it might seem strange that you're processing an asynchronous call synchronously, but this typically only happens if there is already a connection waiting to be accepted when AcceptAsync is called. Since there's already a connection there, there is no need to go through an asyncronous I/O call, and processing it synchronously is faster and uses less resources.

Mystere Man
A: 

Even by calling Thread.Sleep on a LAN so that I am sure all the data has arrived from the client, I cannot make either the AcceptAsync or ReceiveAsync return false with the default Socket options using TCP. I wonder if it is possible to return false using some unique options, or UDP, or maybe on a Send with NoDelay option. Anyway, it's easy to code for the possibility of it returning false.

Stan Kirk
A: 

If the method returned false it means: the operation has already completed.

So if it returns true the operation hasn't completed yet.

To sum it up:

  • If the method returns false, handle it immediately.
  • If the method returns true, handle it when the event is fired.

Hope this helped.

Kevin