private static async Task ReceiveAsync(WebSocket webSocket, IWebSocketsClient client) { var buffer = new byte[1024 * 4]; var result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { var data = buffer.Slice(0, result.Count); await client.ReceiveAsync(data); result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); } await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); }
public static async Task ReceiveAsync(this WebSocket webSocket, IWebSocketsClient client) { int currentMessageLength = 0; byte[] buffer = new byte[1024 * 4]; byte[] combinedData = Array.Empty <byte>(); WebSocketReceiveResult result = null; Task <WebSocketReceiveResult> receiveBeforeTheLoop = webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); await receiveBeforeTheLoop.ContinueWith(t => { if (t.IsFaulted) { // TODO: how to log it from here } if (t.IsCompletedSuccessfully) { result = t.Result; } }); if (result == null) { // TODO: how to log it from here return; } while (result.MessageType != WebSocketMessageType.Close) { int newMessageLength = currentMessageLength + result.Count; if (newMessageLength > _maxPooledSize) { throw new InvalidOperationException("Message too long"); } byte[] newBytes = ArrayPool <byte> .Shared.Rent(newMessageLength); buffer.AsSpan(0, result.Count).CopyTo(newBytes.AsSpan(currentMessageLength, result.Count)); if (!ReferenceEquals(combinedData, Array.Empty <byte>())) { combinedData.AsSpan(0, currentMessageLength).CopyTo(newBytes.AsSpan(0, currentMessageLength)); ArrayPool <byte> .Shared.Return(combinedData); } combinedData = newBytes; currentMessageLength = newMessageLength; if (result.EndOfMessage) { Memory <byte> data = combinedData.AsMemory().Slice(0, currentMessageLength); await client.ReceiveAsync(data); currentMessageLength = 0; ArrayPool <byte> .Shared.Return(combinedData); combinedData = Array.Empty <byte>(); } Task <WebSocketReceiveResult> receiveInTheLoop = webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); await receiveInTheLoop.ContinueWith(t => { if (t.IsFaulted) { result = null; // TODO: how to log it from here } if (t.IsCompletedSuccessfully) { result = t.Result; } }); if (result == null) { // TODO: how to log it from here return; } } await webSocket.CloseAsync(result.CloseStatus ?? WebSocketCloseStatus.Empty, result.CloseStatusDescription, CancellationToken.None); }