Pergunta

I am experimenting with building a socket server in C# and one issue I am stuck on is that when I pass an AsyncCallback to my socket's BeginReceive method the callback is being called too soon and I am getting null when I read the IAsyncResult's AsyncState property.

I thought I had 'fixed' this by adding

.AsyncWaitHandle.WaitOne(100);

But the problem is still occurring. Could anyone shed any light on where what I'm doing wrong?

My code is as follows (abbreviated):

   private void Main(){

        _listener.BeginAccept(new AsyncCallback(HandleConnection), null);
    }


    private void HandleConnection(IAsyncResult status)
    {
        SocketError socketRecieveError;

        _connectionSocket = _listener.EndAccept(status);
        _connectionSocket.BeginReceive(_receivedDataBuffer, 0, _receivedDataBuffer.Length, 0, out socketRecieveError,
                                      new AsyncCallback(HandleHandshake), _connectionSocket.Available);

        if(socketRecieveError !=  SocketError.Success)
            _logger.Log("Socket error: " + socketRecieveError);
    }


    private void HandleHandshake(IAsyncResult status)
    {

        status.AsyncWaitHandle.WaitOne(1000);

        int handshakeLength;

        try
        {
            handshakeLength = Convert.ToInt32(status.AsyncState); // <--- BOOOM
        }
        catch (Exception ex)
        {
            _logger.Log(ex.Message);
        }
 ..............
 }
Foi útil?

Solução

The AsyncState property of IAsyncResult contains the user-defined object that contains information about the asynchronous operation (MSDN). This is the same object that is supplied as parameter "state" when the asynchronous operation is invoked.

In your code, you supply _connectionSocket.Available as user state. I suppose you want to provide your callback method with the number of bytes that were received? This is not the right way to do it.

The would be the correct way to do it:

private void HandleConnection(IAsyncResult status)
{
    SocketError socketRecieveError;

    _connectionSocket = _listener.EndAccept(status);
    _connectionSocket.BeginReceive(_receivedDataBuffer, 0, _receivedDataBuffer.Length, 0, out socketRecieveError, new AsyncCallback(HandleHandshake), null);

    if(socketRecieveError !=  SocketError.Success)
        _logger.Log("Socket error: " + socketRecieveError);
}

private void HandleHandshake(IAsyncResult ar)
{
    int bytesReceived = _connectionSocket.EndReceive(ar);

    ....
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top