protected override async Task ProtectedWriteAsync( byte[] buffer, int offset, int count, CancellationToken cancellationToken) { VerifyConnectionNotClosedAlready(); try { TraceSources.Compute.TraceVerbose($"WebSocketStream: begin WriteAsync({count} bytes)... [socket: {this.socket.State}]"); await this.socket.SendAsync( new ArraySegment <byte>(buffer, offset, count), WebSocketMessageType.Binary, true, cancellationToken).ConfigureAwait(false); TraceSources.Compute.TraceVerbose($"WebSocketStream: end WriteAsync()... [socket: {this.socket.State}]"); } catch (Exception e) when(IsSocketError(e, SocketError.ConnectionAborted)) { TraceSources.Compute.TraceVerbose($"WebSocketStream.Send: connection aborted - {e}"); this.closeByServerReceived = new WebSocketStreamClosedByServerException( WebSocketCloseStatus.NormalClosure, e.Message); throw this.closeByServerReceived; } }
protected override async Task <int> ProtectedReadAsync( byte[] buffer, int offset, int count, CancellationToken cancellationToken) { VerifyConnectionNotClosedAlready(); // Check buffer size. Zero-sized buffers are allowed for // connection probing. if (count > 0 && count < this.MinReadSize) { throw new IndexOutOfRangeException($"Read buffer too small, must be at least {this.MinReadSize}"); } try { int bytesReceived = 0; WebSocketReceiveResult result; do { if (bytesReceived > 0 && bytesReceived == count) { throw new OverflowException("Buffer too small to receive an entire message"); } TraceSources.Compute.TraceVerbose($"WebSocketStream: begin ReadAsync()... [socket: {this.socket.State}]"); result = await this.socket.ReceiveAsync( new ArraySegment <byte>( buffer, offset + bytesReceived, count - bytesReceived), cancellationToken).ConfigureAwait(false); bytesReceived += result.Count; TraceSources.Compute.TraceVerbose($"WebSocketStream: end ReadAsync() - {result.Count} bytes read [socket: {this.socket.State}]"); }while (count > 0 && !result.EndOfMessage); if (result.CloseStatus != null) { Debug.Assert(bytesReceived == 0); TraceSources.Compute.TraceVerbose($"Connection closed by server: {result.CloseStatus}"); this.closeByServerReceived = new WebSocketStreamClosedByServerException( result.CloseStatus.Value, result.CloseStatusDescription); // In case of a normal close, it is preferable to simply return 0. But // if the connection was closed abnormally, the client needs to know // the details. if (result.CloseStatus.Value != WebSocketCloseStatus.NormalClosure) { throw this.closeByServerReceived; } else { Debug.Assert(bytesReceived == 0); } } return(bytesReceived); } catch (Exception e) when(IsSocketError(e, SocketError.ConnectionAborted)) { TraceSources.Compute.TraceVerbose($"WebSocketStream.Receive: connection aborted - {e}"); // ClientWebSocket/WinHttp can also throw an exception if // the connection has been closed. this.closeByServerReceived = new WebSocketStreamClosedByServerException( WebSocketCloseStatus.NormalClosure, e.Message); throw this.closeByServerReceived; } }