System.ObjectDisposedException выдается при связи через WebSocket

Я пытаюсь установить связь между клиентом веб-браузера и сервером ASP.NET с помощью WebSockets.

Я делаю набор запросов разного размера и с интервалом в несколько секунд между каждым из них. Первые три проходят корректно, но точный, ничего особенного от другого, закрывает соединение WebSocket, выдает исключение на стороне сервера.

Сообщение об ошибке и трассировка стека этого исключения выглядят следующим образом:

НЕУСТРАНИМАЯ ОШИБКА: невозможно получить доступ к удаленному объекту.
Имя объекта: «System.Web.WebSockets.AspNetWebSocket».
в System.Web.WebSockets.AspNetWebSocket.ThrowIfDisposed()
в System.Web.WebSockets. AspNetWebSocket.SendAsyncImpl(буфер ArraySegment 1, тип сообщения WebSocketMessageType, логическое значение endOfMessage, CancellationToken CancellationToken, логическое значение PerformValidation)
в System.Web.WebSockets.AspNetWebSocket.SendAsync(буфер ArraySegment 1, тип сообщения WebSocketMessageType, логическое значение endOfMessage, CancellationToken CancellationToken)
в [мой путь к коду здесь...]

Это может быть проблема с потоками, потому что я везде использую методы async из функций, которые взаимодействуют с веб-сокетами.

Я знаю, что исключение выдается из этого кода (в socket.SendAsync):

public class SocketTranslater
{

    private WebSocket socket;
    private JavaScriptSerializer serializer;

    // [...]

    private ArraySegment<byte> Encode(Object data)
    {
        string json = serializer.Serialize(data);
        return (new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)));
    }


    public async Task Send(Object packet)
    {
        ArraySegment<byte> encoded = this.Encode(packet);

        await socket.SendAsync(encoded, WebSocketMessageType.Text, true, CancellationToken.None);
    }
}

Сокет создается из другого класса:

public class EventSender : IHttpHandler
{
    private static List<SocketTranslater> socketTranslaters = new List<SocketTranslater>();

    public void ProcessRequest(HttpContext context)
    {
        this.id = context.Request.UserHostName + ":" + context.Request.UserAgent;
        if (context.IsWebSocketRequest)
        {
            context.AcceptWebSocketRequest(ProcessSocket);
        }        
    }

    private async Task ManageSocket(AspNetWebSocketContext context)
    {
        WebSocket socket = context.WebSocket;
        SocketTranslater translater = new SocketTranslater(socket);
        translaters.add(translater);

        while (true)
        {
            // Manage messages, using the other class to send responses.
            translater.Send(/* Any struct here */);
        }
    }

К сожалению, мой проект слишком велик, чтобы разместить здесь весь код.

Любая идея источника ошибки или дополнительная информация, которая вам потребуется?

ОБНОВЛЕНИЕ:

После еще нескольких тестов у меня время от времени нет этого исключения. Я всегда делаю одно и то же, но сервер, кажется, ведет себя случайным образом.

Это делает мою проблему еще более странной...


person Aracthor    schedule 29.04.2015    source источник
comment
выложи код, без него мы мало чем сможем помочь   -  person DLeh    schedule 29.04.2015


Ответы (1)


Наконец, после еще нескольких тестов и интересных вопросов и ответов отсюда (например, этот), я понял:

Моя проблема заключалась в том, что я хранил веб-сокеты в словаре, связанном с именами хостов. Так что при первом подключении клиента к моему серверу все работало корректно. Но если я обновляю страницу, веб-сокет закрывается сервером (потому что не было возможности использовать его снова) и создается другой.

Но поскольку я использовал один и тот же ключ для обоих сокетов, устаревшего и нового, я пытался ответить новому клиенту с помощью предыдущего сокета, который был закрыт. (распоряжение = закрыто для ASP.NET).

Так что единственное, что мне нужно было сделать, это удалить сокет из списка при отключении клиента (в конце ManageSocket). И запретить клиенту подключаться дважды с одним и тем же именем хоста.

Я не упомянул ту часть, где я связывал сокеты с именами хостов, поэтому я признаю, что вы не могли мне помочь... Прошу прощения.

person Aracthor    schedule 30.04.2015
comment
но как? Не могли бы вы вставить пример использования? Похоже, что WebSocket расположен сразу после этой функции, но я хочу сохранить его на потом. Это возможно? - person bunny1985; 06.06.2017
comment
@ bunny1985 Извините, но я опубликовал этот ответ два года назад, и, поскольку с тех пор я никогда больше не использовал asp.net, я понятия не имею, как я это сделал. И у меня не осталось кода, чтобы поделиться примером. - person Aracthor; 06.06.2017