Протокол Java Socket RPC - PullRequest
       2

Протокол Java Socket RPC

3 голосов
/ 17 февраля 2011

Я задавал несколько вопросов об адаптации протокола команд для использования в моей клиент-серверной среде. Однако после некоторых экспериментов я пришел к выводу, что это не будет работать для меня. Он не предназначен для этого сценария. Я, таким образом, в свободном конце.

До этого я реализовывал своего рода механизм RPC, в результате чего у меня был класс под названием «Операция». У меня также был enum, озаглавленный «Действие», который содержал имена для действий, которые могли быть вызваны на сервере.

Теперь в моем старом проекте каждый раз, когда клиент хотел вызвать действие на сервере, он создавал экземпляр «Operation» и устанавливал переменную action со значением из перечисления «Action». Например

Operation serverOpToInvoke = new Operation();<br /> serverOpToInvoke.setAction(Action.CREATE_TIME_TABLE);<br /> serverOpToInvoke.setParameters(Map params);<br /> ServerReply reply = NetworkManager.sendOperation(serverOpToInvoke);<br /> ...

На стороне сервера мне пришлось выполнить ужасную задачу по определению, какой метод вызывать, изучив значение перечисления 'Action' с загрузкой операторов if / else. Когда совпадение было найдено, я бы вызвал соответствующий метод.

Проблема с этим заключалась в том, что он был грязным, сложным в обслуживании и в конечном итоге был плохим дизайном.

У меня такой вопрос: есть ли какой-то шаблон, которому я могу следовать, чтобы реализовать хороший, чистый и поддерживаемый механизм rpc через сокет TCP в java? RMI мне не подходит, так как клиент (Android) не поддерживает RMI. Я исчерпал все возможности на этом этапе. Единственным другим вариантом может быть услуга REST. Любой совет будет очень полезным.

Большое спасибо Привет

Ответы [ 3 ]

8 голосов
/ 17 февраля 2011

Вероятно, самое простое решение - свободно следовать по пути RMI.

Вы начинаете с интерфейса и реализации:

interface FooService  {
  Bar doThis( String param );
  String doThat( Bar param );
}

class FooServiceImpl implements FooService {
  ...
}

Вы развертываете интерфейс с обеих сторон иреализация только на стороне сервера.

Затем, чтобы получить объект клиента, вы создаете динамический прокси.Его обработчик вызовов не будет делать ничего другого, кроме как сериализовать имя класса службы, имя метода и параметры и отправить его на сервер (изначально вы можете использовать ObjectOutputStream, но вы можете использовать альтернативные методы сериализации, например, XStream).

Слушатель сервера принимает этот запрос и выполняет его, используя отражение, а затем отправляет ответ обратно.

Реализация довольно проста и прозрачна с обеих сторон, единственным серьезным предостережением является то, что ваши службы будутэффективно быть одиночками.

Я могу включить некоторые дополнительные детали реализации, если вам нужно, но это общая идея, которой я бы следовал, если бы мне пришлось реализовать что-то подобное.

Сказав это, яВозможно, пришлось бы поискать немного больше уже существующего решения, такого как веб-сервисы или что-то подобное.

Обновление: Это то, что будет делать обычный (локальный) обработчик вызовов.

class MyHandler implements InvocationHandler {

    private Object serviceObject;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        return method.invoke(serviceObject, args);
    }
}

Где serviceObject - объект реализации вашего сервисак обработчику.

Это то, что вы должны разрезать пополам, и вместо вызова метода вам необходимо отправить на сервер следующее:

  1. Полное имяинтерфейс (или другое значение, однозначно идентифицирующее интерфейс службы)
  2. Название метода.
  3. Имена типов параметров, ожидаемых методом.
  4. The args массив.

Серверная сторона должна будет:

  1. Найти реализацию для этого интерфейса (самый простой способ - создать карту с ключамиимена интерфейсов и значения экземпляра синглтона реализации)
  2. Найдите метод, используя Class.getMethod( name, paramTypes );
  3. Выполните метод, вызвав method.invoke(serviceObject, args); и отправив возвращаемое значение обратно.
2 голосов
/ 23 февраля 2011

Вы должны посмотреть на буферы протокола от Google: http://code.google.com/p/protobuf/

Эта библиотека определяет IDL для генерации структуроподобных классов, которые можно записывать и читать из потока / байтового массива / и т. Д. Они также определяют механизм RPC, используя определенные сообщения.

Я использовал эту библиотеку для аналогичной проблемы, и она работала очень хорошо.

0 голосов
/ 17 февраля 2011

RMI - это путь.

Java RMI - это интерфейс прикладного программирования Java, который выполняет объектно-ориентированный эквивалент удаленных вызовов процедур (RPC).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...