Exemplo n.º 1
0
        /// <summary>
        /// Sends a message to the server and returns the response received.
        /// </summary>
        /// <typeparam name="Response">The type of response. This should be a ISerializable.</typeparam>
        /// <param name="message">The request to send.</param>
        /// <returns>The response or <c>null</c> if the message couldn't be fetched because the server disconnected.</returns>
        public async Task <TResponse> SendRequest <TResponse>(MessageBase request) where TResponse : class
        {
            try
            {
                this.socket.Send(await MessageUtils.SerializeMessage(request));

                // Read the message header
                byte[] buffer        = new byte[MessageHeader.HeaderSize];
                int    bytesReceived = await this.socket.ReceiveAsync(buffer);

                if (bytesReceived == 0)
                {
                    // We got disconnected from the server, return null.
                    this.Disconnect();
                    return(null);
                }
                else if (bytesReceived != buffer.Length)
                {
                    // We couldn't read the message header. Force a disconnect, and return null.
                    this.Disconnect();
                    return(null);
                }

                MessageType messageType;
                int         messageID   = 0;
                int         messageSize = 0;
                using (var memoryStream = new MemoryStream(buffer))
                {
                    var messageHeader = MessageUtils.DeserializeMessageHeader(memoryStream);
                    messageSize = messageHeader.Size;
                    messageID   = messageHeader.ID;
                    messageType = messageHeader.Type;
                }

                int    totalSizeRead = 0;
                byte[] messageData   = new byte[messageSize];
                do
                {
                    int bytesRemaining = messageData.Length - totalSizeRead;
                    bytesReceived = await this.socket.ReceiveAsync(messageData, totalSizeRead, bytesRemaining, SocketFlags.None);

                    if (bytesReceived == 0)
                    {
                        this.Disconnect();
                        return(null);
                    }

                    totalSizeRead += bytesReceived;
                }while (totalSizeRead < messageSize);

                if (messageType == MessageType.Response)
                {
                    // Deserialize the message, and return it.
                    using (var memoryStream = new MemoryStream(messageData))
                    {
                        var formatter = new BinaryFormatter();
                        return((TResponse)formatter.Deserialize(memoryStream));
                    }
                }
                else
                {
                    // Deserialize the message, and throw the error.
                    using (var memoryStream = new MemoryStream(messageData))
                    {
                        var formatter = new BinaryFormatter();
                        var error     = (ErrorResponse)formatter.Deserialize(memoryStream);

                        throw new ResponseException(error.Message);
                    }
                }
            }
            catch (SocketException ex) when(ex.ErrorCode == 10054)
            {
                // The server disconnected on us, return null.
                this.Disconnect();
                return(null);
            }
            catch (BadHeaderException)
            {
                // The header is malformed, return null.
                this.Disconnect();
                return(null);
            }
        }