.NET Core JsonDocument.Parse (ReadOnlyMemory <Byte>, JsonReaderOptions) не удалось выполнить анализ из WebSocket ReceiveAsync - PullRequest
0 голосов
/ 19 июня 2019

Я использую .NET Core 3.0 JsonDocument.Parse(ReadOnlyMemory<Byte>, JsonReaderOptions) для синтаксического анализа сообщения WS (byte[]) в JSON, но выдается исключение, как показано ниже:

'0x00' is invalid after a single JSON value. Expected end of data. LineNumber: 0 | BytePositionInLine: 34.

Это мой фрагмент кода Middleware:

WebSocket ws = await context.WebSockets.AcceptWebSocketAsync();
byte[] bytes = new byte[1024 * 4];
ArraySegment<byte> buffer = new ArraySegment<byte>(bytes);

while (ws.State == WebSocketState.Open)
{
       try
       {
             WebSocketReceiveResult request = await ws.ReceiveAsync(bytes, CancellationToken.None);
             switch (request.MessageType)
             {
                     case WebSocketMessageType.Text:
                             string msg = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                             json = new ReadOnlyMemory<byte>(bytes);
                             JsonDocument jsonDocument = JsonDocument.Parse(json);
                             break;
                     default:
                             break;
             }
       }
       catch (Exception e)
       {
             Console.WriteLine($"{e.Message}\r\n{e.StackTrace}");
       }
 }

1 Ответ

0 голосов
/ 19 июня 2019

Как уже упоминалось в комментариях, вы сделали несколько ошибок. Одним из самых больших является то, что вы выделяете память (в конечном итоге это приводит к выделению ресурсов и gc, чего хочет избежать интерфейс Memory / Span API). Во-вторых, вы не разбивали свои данные на части, поскольку полезная нагрузка меньше размера буфера.

Некоторые исправления, которые я сделал для кода

WebSocket ws = await context.WebSockets.AcceptWebSocketAsync();
// Don't do that, it allocates. Beats the main idea of using [ReadOnly]Span/Memory
// byte[] bytes = new byte[1024 * 4];

// We don't need this either, its old API. Websockets support Memory<byte> in an overload
// ArraySegment<byte> buffer = new ArraySegment<byte>(bytes);

// We ask for a buffer from the pool with a size hint of 4kb. This way we avoid small allocations and releases
// P.S. "using" is new syntax for using(disposable) { } which will
// dispose at the end of the method. new in C# 8.0
using IMemoryOwner<byte> memory = MemoryPool<byte>.Shared.Rent(1024 * 4);

while (ws.State == WebSocketState.Open)
{
    try
    {
        ValueWebSocketReceiveResult request = await ws.ReceiveAsync(memory.Memory, CancellationToken.None);
        switch (request.MessageType)
        {
            case WebSocketMessageType.Text:
                // we directly work on the rented buffer
                string msg = Encoding.UTF8.GetString(memory.Memory.Span);
                // here we slice the memory. Keep in mind that this **DO NOT ALLOCATE** new memory, it just slice the existing memory
                // reason why it doesnt allocate is, is that Memory<T> is a struct, so its stored on the stack and contains start 
                // and end position of the sliced array
                JsonDocument jsonDocument = JsonDocument.Parse(memory.Memory.Slice(0, request.Count));
                break;
            default:
                break;
        }
    }
    catch (Exception e)
    {
        Console.WriteLine($"{e.Message}\r\n{e.StackTrace}");
    }
}

Вам нужно нарезать его, чтобы синтаксический анализатор Json не читал за пределами строки JSON.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...