Крионет. RMI. Время ответа истекло при попытке выполнить удаленный метод

Я пытаюсь запустить простой проект kryonet RMI с двумя отдельными клиентскими и серверными приложениями.

Но когда я пытаюсь выполнить метод удаления - это приводит к:

Exception in thread "main" com.esotericsoftware.kryonet.rmi.TimeoutException: Response timed out: jemmy.IJemmyCommander.run
at com.esotericsoftware.kryonet.rmi.ObjectSpace$RemoteInvocationHandler.invoke(ObjectSpace.java:408)
at com.sun.proxy.$Proxy0.run(Unknown Source)
at jemmy.dummy.client.RunClient.main(RunClient.java:29)

Есть исходный код: server и client.

Как заставить его работать? Он должен напечатать "Выполнить" на консоли сервера.


person Viktor Sidochenko    schedule 20.02.2016    source источник


Ответы (1)


В ваших проектах есть несколько проблем:

  1. У вас должна быть общая модель данных между вашим клиентом и вашим сервером. Вы можете оставить серверные классы приватными, но они должны реализовывать интерфейсы, известные вашему клиенту.

Когда клиент вызывает метод удаленного объекта, он отправляет по сети InvokeMethod с идентификатором удаленного объекта и методом. На сервере выполняется поиск объекта и вызывается метод. Если интерфейсы не совпадают, вы получите исключение «объект не является экземпляром объявления класса».

  1. Вы должны использовать одну и ту же конфигурацию для вашего Kryo экземпляра: ваш клиент и ваш сервер должны зарегистрировать одни и те же классы в одном порядке.

У Kryo есть соответствие между именами классов и внутренним идентификатором. Если вы зарегистрируете класс явно, этот класс будет использовать идентификатор, чтобы минимизировать трафик. Если вы зарегистрируете на своем сервере один и тот же класс с другим идентификатором, тогда клиент и сервер не будут соответствовать одним и тем же классам, и сообщение не будет выполнено.

  1. На своем сервере вы должны зарегистрироваться через ObjectSpace объекты, которые могут быть вызваны вашим клиентом.

ObjectSpace - это реестр удаленных объектов. Он отвечает за создание прокси и обработчик InvokeMethod сообщений. На сервере вы должны связать каждое соединение с одним или несколькими ObjectSpace.

В вашем проекте:

  1. Создайте третью банку, содержащую общие интерфейсы между вашим клиентом и вашим сервером. Эта банка также может содержать вспомогательный класс для создания экземпляра Kryo. Проще, просто создайте зависимость от вашего сервера к вашему клиенту и зарегистрируйте те же классы (необходимо только IJemmyCommander)

  2. Сделайте JemmyCommand орудия IJemmyCommand

  3. На вашем сервере добавьте:

    server.addListener(new Listener() {
       @Override
       public void connected(Connection connection) {
          // 44 is the identifier of the JemmyCommander, referenced by a client
          new ObjectSpace(connection).register(44, new JemmyCommander());
       }
    });
    
person Jérémie B    schedule 21.02.2016
comment
Спасибо за ответ. Добавление слушателя решает проблему. Непонятная документация по нему в крионете. Но совсем не обязательно, чтобы класс сервера реализовал интерфейс (согласно документации, я это тестировал) - он разрешается через идентификаторы. - person Viktor Sidochenko; 22.02.2016
comment
И вопрос: закрывать объект на отключенном клиенте, или он будет удален автоматически? - person Viktor Sidochenko; 22.02.2016
comment
Вам не обязательно использовать интерфейсы, но класс, используемый вашим клиентом, должен быть известен вашему серверу: если вы не хотите делиться деталями своей реализации между клиентом и сервером, лучше использовать интерфейсы. Для вашего второго вопроса вы можете реализовать disconnected на своем слушателе для некоторой очистки. если у вас есть общий ObjectSpace, вы должны позвонить removeConnection, если нет, в этом нет необходимости - person Jérémie B; 22.02.2016