Получение сообщений с использованием класса ClientWebSocket вызывает исключение: веб-сайт получил кадр с одним или несколькими зарезервированными битами

#c# #.net #websocket #real-time #clientwebsocket

Вопрос:

Я хотел бы создать клиент websocket для подключения к стороннему серверу веб-сокетов.

Я использую класс ClientWebSocket:

 public WSClientService(ClientWebSocket client, ILogger<WSClientService> logger)
{
    _client = client;
    _logger = logger;
}
 

Для получения сообщений я использую этот метод:

 public async Task GetMessagesAsync()
{
    while (_client.State == WebSocketState.Open)
    {
        var chunkSize = 1024 * 4;
        var buffer = new ArraySegment<byte>(new byte[chunkSize]);

        do
        {
            WebSocketReceiveResult resu<
            using var ms = new MemoryStream();
            try
            {
                do
                {
                    //here throws exception
                    result = await _client.ReceiveAsync(buffer, CancellationToken.None);
                    ms.Write(buffer.Array, buffer.Offset, result.Count);
                } while (!result.EndOfMessage);

                if (result.MessageType == WebSocketMessageType.Close)
                {
                    break;
                }

                ms.Seek(0, SeekOrigin.Begin);
                using var reader = new StreamReader(ms, Encoding.UTF8);
                var message = await reader.ReadToEndAsync();
                _logger.LogInformation(message);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
            }

        } while (_client.State != WebSocketState.Aborted);                
    }
}
 

Но для некоторых сообщений я получаю это сообщение об исключении :
The WebSocket received a frame with one or more reserved bits set
Я заметил, что это происходит, вероятно, из-за некоторого сжатия, потому что я могу получать небольшие сообщения. Исключение, возникающее при вызове этого result = await _client.ReceiveAsync(buffer, CancellationToken.None);

Кто-нибудь знает, как решить эту проблему?

Ответ №1:

Решение пришло с выпуском .net 6. Ну, проблема возникла из-за того, что не было возможности добавить сжатие во встроенный ClientWebSocket в .net 5 и обратно (за исключением случаев, когда кто-то создавал метод расширения для сжатия). Теперь в .net 6 появилась новая опция с именем DangerousDeflateOptions . Это также добавляет соответствующий заголовок.

 _ws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions
{
    ServerContextTakeover = false,
    ClientMaxWindowBits = 15 // this is the default value
};

await _ws.ConnectAsync(new Uri(_url), token).ConfigureAwait(false);