/// <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); } }