A websocket's ReceiveAsync method does not await the entire message

后端 未结 5 2062
借酒劲吻你
借酒劲吻你 2020-12-05 11:45

I am receiving JSON through a websocket. At least: I am partially. Using an online websocket service I receive the full JSON response (all the HTML markup is ignored). When

相关标签:
5条回答
  • 2020-12-05 12:02

    Just to complete @Noseratio response, the code would be something like this:

    ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[8192]);
    
    WebSocketReceiveResult result= null;
    
    using (var ms = new MemoryStream())
    {
         do
         {
             result = await socket.ReceiveAsync(buffer, CancellationToken.None);
             ms.Write(buffer.Array, buffer.Offset, result.Count);
         }
         while (!result.EndOfMessage);
    
         ms.Seek(0, SeekOrigin.Begin);
    
         if (result.MessageType == WebSocketMessageType.Text)
         {
              using (var reader = new StreamReader(ms, Encoding.UTF8))
              {
                   // do stuff
              }
         }
    }
    

    Cheers.

    0 讨论(0)
  • 2020-12-05 12:02

    Try this:

    try
    {
        WebSocketReceiveResult result;
        string receivedMessage = "";
        var message = new ArraySegment<byte>(new byte[4096]);
        do
        {
            result = await WebSocket.ReceiveAsync(message, DisconectToken);
            if (result.MessageType != WebSocketMessageType.Text)
                break;
            var messageBytes = message.Skip(message.Offset).Take(result.Count).ToArray();
            receivedMessage += Encoding.UTF8.GetString(messageBytes);                    
        }
        while (!result.EndOfMessage);
        if (receivedMessage != "{}" && !string.IsNullOrEmpty(receivedMessage))
        {
            ResolveWebSocketResponse.Invoke(receivedMessage, Connection);
            Console.WriteLine("Received: {0}", receivedMessage);
        }
    }
    catch (Exception ex)
    {
        var mes = ex.Message;
    }
    
    0 讨论(0)
  • 2020-12-05 12:07

    I might be wrong, but I don't think you're always supposed to receive a complete WebSocket message at once. The server may be sending the message in chunks (that'd correspond to calling SendAsync with endOfMessage: false).

    So, do await _socket.ReceiveAsync() in a loop and accumulate the received chunks, until WebSocketReceiveResult.EndOfMessage is true or an error has occured.

    On a side note, you probably should be using WebSocket.CreateClientBuffer instead of new ArraySegment<byte>(buffer).

    0 讨论(0)
  • 2020-12-05 12:11
    // Read the bytes from the web socket and accumulate all into a list.
    var buffer = new ArraySegment<byte>(new byte[1024]);
    WebSocketReceiveResult result = null;
    var allBytes = new List<byte>();
    
    do
    {
        result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
        for (int i = 0; i < result.Count; i++)
        {
            allBytes.Add(buffer.Array[i]);
        }
    }
    while (!result.EndOfMessage);
    
    // Optional step to convert to a string (UTF-8 encoding).
    var text = Encoding.UTF8.GetString(allBytes.ToArray(), 0, allBytes.Count);
    
    0 讨论(0)
  • 2020-12-05 12:16

    Following Noseratio's answer I have implemented a temporary buffer that will construct the data of the entire message.

    var temporaryBuffer = new byte[BufferSize];
    var buffer = new byte[BufferSize * 20];
    int offset = 0;
    WebSocketReceiveResult response;
    
    while (true)
    {
        response = await _socket.ReceiveAsync(
                             new ArraySegment<byte>(temporaryBuffer), 
                             CancellationToken.None);
        temporaryBuffer.CopyTo(buffer, offset);
        offset += response.Count;
        temporaryBuffer = new byte[BufferSize];
        if (response.EndOfMessage)
        {
            break;
        }
    }
    

    Full implementation here

    0 讨论(0)
提交回复
热议问题