예제 #1
0
        /// <summary>
        /// Receive a WebSocket message.
        /// </summary>
        /// <returns>A ReceivedMessage object containing Result and Message.</returns>
        private async Task <WsClientReceivedMessage> ReceiveMessageAsync()
        {
            WsClientReceivedMessage receivedMessage = new WsClientReceivedMessage
            {
                Message = new MemoryStream()
            };

            do
            {
                try
                {
                    receivedMessage.Result = await _Client.ReceiveAsync(receiveBuffer, CancellationToken.None).ConfigureAwait(false);
                }
                catch (WebSocketException e)
                {
                    receivedMessage.Message.Dispose();
                    receivedMessage.Message = null;
                    if (_Client != null)
                    {
                        OnStateChange(_Client.State);
                    }
                    else
                    {
                        OnStateChange(WebSocketState.None);
                    }
                    OnErrorState(e, -1);
                    break;
                }
                receivedMessage.Message.Write(receiveBuffer.Array, receiveBuffer.Offset, receivedMessage.Result.Count);
            } while (!receivedMessage.Result.EndOfMessage);

            return(receivedMessage);
        }
예제 #2
0
        /// <summary>
        /// Starts an asynchronous loop for receiving WebSocket messages.
        /// </summary>
        public async Task StartMessageReceiveLoop()
        {
            // Only one message can be received at a time. Wait until we can control the receive queue.
            await receiveAsyncSemaphore.WaitAsync().ConfigureAwait(false);

            // Store the context of our thread so we can release receiveAsyncSemaphore later.
            SynchronizationContext receiveLoopContext = SynchronizationContext.Current ?? new SynchronizationContext();

            // The long-lived while loop should run synchronously.
            while (_Status == WebSocketState.Open || _Status == WebSocketState.CloseReceived)
            {
                try
                {
                    // There can be a long time between messages received... does it matter which thread picks up the next one?
                    WsClientReceivedMessage receivedMessage = await ReceiveMessageAsync().ConfigureAwait(false);

                    // There should currently only be three MessageType: Close, Text, and Binary.
                    const int expectedMessageTypeCount = 3;
                    Debug.Assert(Enum.GetNames(typeof(WebSocketMessageType)).Length == expectedMessageTypeCount, $"StartMessageReceiveLoop expected {expectedMessageTypeCount} MessageType, there are {Enum.GetNames(typeof(WebSocketMessageType)).Length}");
                    // Result is null if a connection issue occurred. MessageType==Close if server is closing connection.
                    if (receivedMessage.Result == null || receivedMessage.Result.MessageType == WebSocketMessageType.Close)
                    {
                        break;
                    }
                    // The two other MessageType are Text and Binary.
                    else if (receivedMessage.Result.MessageType == WebSocketMessageType.Text || receivedMessage.Result.MessageType == WebSocketMessageType.Binary)
                    {
                        ParseMessage(receivedMessage);
                    }
                    else
                    {
                        /* Impossible condition unless:
                         * (a) RFC 6455 is updated,
                         * (b) ClientWebSocket includes a new websocket protocol OpCode,
                         * (c) This library hasn't been debugged since (b) made it into a new .NET Core version.
                         * In such a case, the above if/elseif needs updating as GenericClient is potentially no longer fit for purpose.
                         */
                        WebSocketException e = new WebSocketException(
                            WebSocketError.InvalidMessageType,
                            String.Format(CultureInfo.CurrentCulture, Properties.Resources.exception_unknown_websocket_message_type_format, typeof(GenericClient).Name, receivedMessage.Result.MessageType)
                            );
                        OnErrorState(e, -1);
                        throw e;
                    }
                }
                catch (WebSocketException e)
                {
                    Debugger.Break();
                    OnStateChange(_Client.State);
                    OnErrorState(e, -1);
                }
            }
            // No more messages can be received on this connection. Get the receiveLoopContext thread to release the receiveAsyncSemaphore.
            receiveLoopContext.Send(
                x => receiveAsyncSemaphore.Release(),
                null);
        }
예제 #3
0
 /// <summary>
 /// Calls correct event invocation method depending on MessageType.
 /// </summary>
 /// <param name="receivedMessage">A ReceivedMessage instance.</param>
 private void ParseMessage(WsClientReceivedMessage receivedMessage)
 {
     receivedMessage.Message.Seek(0, SeekOrigin.Begin);
     if (receivedMessage.Result.MessageType == WebSocketMessageType.Text)
     {
         OnReceiveTextMessage(receivedMessage.Message);
     }
     else if (receivedMessage.Result.MessageType == WebSocketMessageType.Binary)
     {
         OnReceiveBinaryMessage(receivedMessage.Message);
     }
 }