.Net Socket: Как лучше реализовать AsyncCallback / AsyncWaitHandle - PullRequest
0 голосов
/ 27 января 2011

Я экспериментирую с созданием сервера сокетов в C #, и одна проблема, на которой я застрял, заключается в том, что когда я передаю AsyncCallback методу BeginReceive моего сокета, вызывается также обратный вызовскоро, и я получаю нулевое значение, когда читаю свойство AsyncState IAsyncResult.

Я думал, что "исправил" это, добавив

.AsyncWaitHandle.WaitOne(100);

Но проблема все еще остаетсяпроисходит.Может ли кто-нибудь пролить свет на то, что я делаю неправильно?

Мой код выглядит следующим образом (сокращенно):

   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);
        }
 ..............
 }

1 Ответ

1 голос
/ 27 января 2011

Свойство AsyncState объекта IAsyncResult содержит определенный пользователем объект, который содержит информацию об асинхронной операции ( MSDN ). Это тот же объект, который предоставляется в качестве параметра «состояние» при вызове асинхронной операции.

В вашем коде вы предоставляете _connectionSocket.Available как пользовательское состояние. Я полагаю, вы хотите предоставить свой метод обратного вызова с количеством байтов, которые были получены? Это не правильный способ сделать это.

Правильный способ сделать это:

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);

    ....
}
...