code: public synchronized Message simpleRequest(Message.KnownType requestType, Message.KnownType responseType,
                                                Field... arguments)
              throws IOException {
          final NumberField transaction = assignTransactionNumber();
          final Message request = new Message(transaction, new NumberField(requestType.protocolValue, 2), arguments);
          sendMessage(request);
          final Message response = Message.read(is);
          if (response.transaction.getValue() != transaction.getValue()) {
              throw new IOException("Received response with wrong transaction ID. Expected: " + transaction.getValue() +
              ", got: " + response);
          }
          if (responseType != null && response.knownType != responseType) {
              throw new IOException("Received response with wrong type. Expected: " + responseType +
              ", got: " + response);
          }
          return response;
      }
docs: Send a request that expects a single message as its response, then read and return that response.
  
  @param requestType identifies what kind of request to send
  @param responseType identifies the type of response we expect, or {@code null} if we’ll accept anything
  @param arguments The argument fields to send in the request
  
  @return the response from the player
  
  @throws IOException if there is a communication problem, or if the response does not have the same transaction
  ID as the request.