public static async Task<WebSocketMessage> ReadMessageAsync(WebSocket webSocket, byte[] buffer, int maxMessageSize) { ArraySegment<byte> arraySegment = new ArraySegment<byte>(buffer); WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(arraySegment, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); // special-case close messages since they might not have the EOF flag set if (receiveResult.MessageType == WebSocketMessageType.Close) { return new WebSocketMessage(null, WebSocketMessageType.Close); } if (receiveResult.EndOfMessage) { // we anticipate that single-fragment messages will be common, so we optimize for them switch (receiveResult.MessageType) { case WebSocketMessageType.Binary: return new WebSocketMessage(BufferSliceToByteArray(buffer, receiveResult.Count), WebSocketMessageType.Binary); case WebSocketMessageType.Text: return new WebSocketMessage(BufferSliceToString(buffer, receiveResult.Count), WebSocketMessageType.Text); default: throw new Exception("This code path should never be hit."); } } else { // for multi-fragment messages, we need to coalesce ByteBuffer bytebuffer = new ByteBuffer(maxMessageSize); bytebuffer.Append(BufferSliceToByteArray(buffer, receiveResult.Count)); WebSocketMessageType originalMessageType = receiveResult.MessageType; while (true) { // loop until an error occurs or we see EOF receiveResult = await webSocket.ReceiveAsync(arraySegment, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); if (receiveResult.MessageType != originalMessageType) { throw new InvalidOperationException("Incorrect message type"); } bytebuffer.Append(BufferSliceToByteArray(buffer, receiveResult.Count)); if (receiveResult.EndOfMessage) { switch (receiveResult.MessageType) { case WebSocketMessageType.Binary: return new WebSocketMessage(bytebuffer.GetByteArray(), WebSocketMessageType.Binary); case WebSocketMessageType.Text: return new WebSocketMessage(bytebuffer.GetString(), WebSocketMessageType.Text); default: throw new Exception("This code path should never be hit."); } } } } }
public static async Task<WebSocketMessage> ReadMessageAsync(WebSocket webSocket, int bufferSize, int? maxMessageSize, CancellationToken disconnectToken) { WebSocketMessage message; // Read the first time with an empty array WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(_emptyArraySegment, disconnectToken).PreserveCultureNotContext(); if (TryGetMessage(receiveResult, null, out message)) { return message; } var buffer = new byte[bufferSize]; // Now read with the real buffer var arraySegment = new ArraySegment<byte>(buffer); receiveResult = await webSocket.ReceiveAsync(arraySegment, disconnectToken).PreserveCultureNotContext(); if (TryGetMessage(receiveResult, buffer, out message)) { return message; } else { // for multi-fragment messages, we need to coalesce ByteBuffer bytebuffer = new ByteBuffer(maxMessageSize); bytebuffer.Append(BufferSliceToByteArray(buffer, receiveResult.Count)); WebSocketMessageType originalMessageType = receiveResult.MessageType; while (true) { // loop until an error occurs or we see EOF receiveResult = await webSocket.ReceiveAsync(arraySegment, disconnectToken).PreserveCultureNotContext(); if (receiveResult.MessageType == WebSocketMessageType.Close) { return WebSocketMessage.CloseMessage; } if (receiveResult.MessageType != originalMessageType) { throw new InvalidOperationException("Incorrect message type"); } bytebuffer.Append(BufferSliceToByteArray(buffer, receiveResult.Count)); if (receiveResult.EndOfMessage) { switch (receiveResult.MessageType) { case WebSocketMessageType.Binary: return new WebSocketMessage(bytebuffer.GetByteArray(), WebSocketMessageType.Binary); case WebSocketMessageType.Text: return new WebSocketMessage(bytebuffer.GetString(), WebSocketMessageType.Text); default: throw new InvalidOperationException("Unknown message type"); } } } } }
public static async Task<WebSocketMessage> ReadMessageAsync(WebSocket webSocket, byte[] buffer, int maxMessageSize, CancellationToken disconnectToken) { var arraySegment = new ArraySegment<byte>(buffer); WebSocketReceiveResult receiveResult = null; try { receiveResult = await webSocket.ReceiveAsync(arraySegment, disconnectToken).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception) { // If the websocket is aborted while we're reading then just rethrow // an operaton cancelled exception so the caller can handle it // appropriately if (webSocket.State == WebSocketState.Aborted) { throw new OperationCanceledException(); } else { // Otherwise rethrow the original exception throw; } } // special-case close messages since they might not have the EOF flag set if (receiveResult.MessageType == WebSocketMessageType.Close) { return new WebSocketMessage(null, WebSocketMessageType.Close); } if (receiveResult.EndOfMessage) { // we anticipate that single-fragment messages will be common, so we optimize for them switch (receiveResult.MessageType) { case WebSocketMessageType.Binary: return new WebSocketMessage(BufferSliceToByteArray(buffer, receiveResult.Count), WebSocketMessageType.Binary); case WebSocketMessageType.Text: return new WebSocketMessage(BufferSliceToString(buffer, receiveResult.Count), WebSocketMessageType.Text); default: throw new Exception("This code path should never be hit."); } } else { // for multi-fragment messages, we need to coalesce ByteBuffer bytebuffer = new ByteBuffer(maxMessageSize); bytebuffer.Append(BufferSliceToByteArray(buffer, receiveResult.Count)); WebSocketMessageType originalMessageType = receiveResult.MessageType; while (true) { // loop until an error occurs or we see EOF receiveResult = await webSocket.ReceiveAsync(arraySegment, disconnectToken).ConfigureAwait(continueOnCapturedContext: false); if (receiveResult.MessageType != originalMessageType) { throw new InvalidOperationException("Incorrect message type"); } bytebuffer.Append(BufferSliceToByteArray(buffer, receiveResult.Count)); if (receiveResult.EndOfMessage) { switch (receiveResult.MessageType) { case WebSocketMessageType.Binary: return new WebSocketMessage(bytebuffer.GetByteArray(), WebSocketMessageType.Binary); case WebSocketMessageType.Text: return new WebSocketMessage(bytebuffer.GetString(), WebSocketMessageType.Text); default: throw new Exception("This code path should never be hit."); } } } } }