使用 ClientWebSocket Class 接收消息抛出异常:WebSocket 收到一个设置了一个或多个保留位的帧

Receiving messages using ClientWebSocket Class throws exception: The WebSocket received a frame with one or more reserved bits set

我想制作一个 websocket 客户端来连接到第三方 web 套接字服务器。

我正在使用 ClientWebSocket Class:

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

时抛出的异常

有人知道如何解决这个问题吗?

解决方案随 .net 6 版本一起发布。好吧,问题的发生是因为无法在 .net 5 及之后的 built-in ClientWebSocket 中添加压缩(除非有人会创建压缩扩展方法)。现在 .net 6 有一个名为 DangerousDeflateOptions 的新选项。这也会添加相应的 header。

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

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