/// <summary> /// Reads the complete next text message from the websocket /// </summary> /// <returns>The text message, or null if socket was closed</returns> private async Task <string> ReceiveNextMessageAsync(IClientWebSocketProxy ws) { _receiveStream.Position = 0; WebSocketReceiveResult result; do { result = await ws.ReceiveAsync(new ArraySegment <byte>(_readBuffer), _cancellationToken.Token); if (result == null || result.Count == 0 || result.MessageType == WebSocketMessageType.Close) { return(null); } if (ws.CloseStatus.HasValue) { return(null); } Debug.Assert(result.MessageType == WebSocketMessageType.Text); if (result.EndOfMessage && _receiveStream.Position == 0) { return(Encoding.UTF8.GetString(_readBuffer, 0, result.Count)); // No need to use memory stream } _receiveStream.Write(_readBuffer, 0, result.Count); }while (!result.EndOfMessage); return(Encoding.UTF8.GetString(_receiveStream.GetBuffer(), 0, (int)_receiveStream.Position)); }
/// <summary> /// Try connecting to the specified websocket url once. /// If the connection is successful, it will complete the function and you don't have to worry /// about reconnects /// </summary> public async Task <bool> TryConnectAsync(Func <string> resolveUrl, string accessToken, Func <Task> postConnectFunc) { if (resolveUrl == null) { throw new ArgumentNullException(nameof(resolveUrl)); } if (_disposed) { throw new ObjectDisposedException(nameof(JsonRpcWebSocket)); } // Local function that will try to reconnect forever async Task reconnect() { while (true) { // Connection lost, wait a little and try again await Task.Delay(GetReconnectDelay(), _cancellationToken.Token); await connect(); if (_ws != null) { return; } } } // Local function used for connect and re-connects async Task connect() { _ws = null; var url = resolveUrl(); try { var ws = CreateWebSocket(accessToken); // Connect the websocket _logger.LogInformation("Connecting to {0}", url); await ws.ConnectAsync(new Uri(url), _cancellationToken.Token).OrTimeout(CONNECT_TIMEOUT); _logger.LogInformation("Connected to {0}", url); _ws = ws; await EatWelcomeMessageAsync().OrTimeout(10000); // start receiving data _receiverTask = Task.Factory.StartNew(() => ReceiverTask(reconnect), TaskCreationOptions.LongRunning); if (postConnectFunc != null) { await postConnectFunc(); } } catch (Exception e) { _ws = null; _logger.LogWarning("Connection to '{0}' failed: {1}", url, e.Message); } } // Do the first time connect await connect(); return(_ws != null); }