Меню Закрыть

Java rmi server hostname

Содержание

Технология RMI (Java Remote Method Invocation) позволяет java-приложению, запущенному на одной виртуальной машине, вызвать методы объекта, работающего на другой виртуальной машине JVM (Java Virtual Machine).

RMI основана на более ранней технологии удаленного вызова процедур Remote Procedure Call (RPC), разработанной в 80-х годах и используемой для процедурного программирования. RPC позволяет процедуре одного приложения вызывать функцию на другом компьютере, как будто эта функция является частью программы. Таким образом, RPC выполняет всю работу по организации сетевых взаимодействий и маршалинга данных (пакетирования параметров функций и возврата значений для передачи их по сети). Но механизм RPC, поддерживающий ограниченный набор простых типов данных, не может использовать объекты Java при обмене информацией. Вторым важным недостатком RPC является необходимость использования специального языка определения интерфейса (IDL) для описания функций, допускающих удаленный вызов. С целью устранения этих недостатков и была разработана технология RMI.

RMI содержит набор объектов (классов) для организации удаленного взаимодействия java-приложений. RMI системы часто включают два отдельных приложения : сервер и клиент. Серверное приложение, как правило, создает удаленные объекты (remote objects), делает доступные ссылки на эти объекты и находится в ожидании вызова методов этих объектов. Клиентское приложение получает у сервера ссылку на удаленные объекты, после чего вызывает его методы. Технология RMI, обеспечивающая механизм взаимодействия клиента и сервера передачей между ними соответствующей информацией, реализована в виде java.rmi пакета, содержащего целый ряд вложенных подпакетов; один из наиболее важных подпакетов java.rmi.server реализует функции сервера RMI.

RMI обеспечивает маршалинг данных по сети и позволяет java приложениям передавать объекты с помощью механизма сериализации объектов. В состав J2SE включены инструментальные средства сетевых взаимодействий из определенных интерфейсов программы; это означает, что RMI не требует от программиста знания языка IDL. Кроме того, никакого нейтрального к языку IDL интерфейса не требуется, так как RMI поддерживает только Java; достаточно собственных интерфейсов Java.

Описание удаленного RMI объекта

Серверный RMI объект должен наследовать (extends) свойства класса java.rmi.server.UnicastRemoteObject, который представляет базовые функциональные возможности, необходимые удаленным объектам для обслуживания удаленных запросов. Конструкторы и методы класса UnicastRemoteObject возбуждают исключение RemoteException.

Конструктор класса UnicastRemoteObject обеспечивает экспорт объекта, чтобы он был доступным для приема удаленных вызовов. Экспорт позволяет удаленному RMI объекту ожидать соединений с клиентами для осуществления взаимодействия типа "точка-точка" с использованием стандартных соединений через сокеты. Предполагается, что клиенты RMI должны осуществлять соединение с использованием порта 1099 для поиска удаленного объекта в реестре RMI сервера. Перегруженный конструктор класса UnicastRemoteObject позволяет определить свой номер порта для экспорта удаленного объекта. Ссылка установления связи с удаленным RMI объектом обычно имеет следующий вид :

где
host представляет собой имя компьютера, в котором определен реестр сервера rmiregistry для удаленных объектов с зарегистрированным удаленным RMI объектом,
port представляет собой номер порта, на котором работает серверное приложение. По умолчанию для реестра RMI объектов используется порт 1099, который можно в этом случае в ссылке не указывать;
object – это имя удаленного RMI объекта, зарегистрированного в реестре сервера.

Читайте также:  Восстановление удаленной теневой копии

Для связывания удаленного RMI объекта с реестром сервера используется один из методов bind или rebind. Метод rebind регистрирует объект в реестре с предварительной проверкой; если объект был ранее зарегистрирован под этим именем, то метод заменит его новым объектом. Это может потребоваться при регистриции новой версии существующего удаленного объекта.

Пример использования RMI

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

Серверное приложение включает три модуля :

• Card – электронная карта;
• BillingService – интерфейс сервиса объекта RMI;
• BillingServiceImpl – объект RMI.

Клиентское приложение также включает три модуля. Пересылаемый по сети объект Card и интерфейс описания RMI объекта BillingService в клиентском приложении должны совпадать с серверными. Третий модуль BillingClient использует интерфейс описания RMI объекта и Card для взаимодействия с объектом RMI, стартованном на сервере.

Листинг карточки, Card

В представленном ниже листинге класса Card.java не отображены методы get/set. Класс Card реализует интерфейс Serializable, который обеспечивает упаковку объекта в байт-коды в одном приложении и преобразования байт-кодов в объект Card в другом приложении.

Листинг RMI сервиса, BillingService

Интерфейс сервиса BillingService наследует свойства java.rmi.Remote и включает методы работы с картой Card. Во всех методах присутствует объект Card, передаваемый по сети между двумя java-приложениями.

Листинг RMI объекта, BillingServiceImpl

Класс BillingServiceImpl представляет собой удаленный объект, реализующий интерфейс BillingService. Чтобы сервер воспринимал его как RMI объект он наследует свойства класса UnicastRemoteObject. Приложение клиента взаимодействует с RMI-объектом типа BillingServiceImpl, вызывая методы addNewCard, addMoney, subMoney, getCardBalance, определенные в интерфейсе BillingService. Объект BillingServiceImpl хранит сведения о картах в коллекции cards.

При старте объекта в методе main определяется системное свойство ‘java.rmi.server.hostname’ как IP адрес локального компьютера (127.0.0.1), формируется и регистрируется в реестре RMI объект.

Старт серверного приложения

Для старта сервера используем командный файл (Window) run.rmi-server.bat со следующим кодом :

После старта серверного приложения в консоль выводится следующая информация :

Сервер переходит в режим ожидания .

Описание клиентского приложения

Как было отмечено выше, клиентское приложение включает 3 файла, два из которых, Card и BillingService, полностью совпадают с серверными. Третий модуль BillingClient для взаимодействия с объектом RMI использует интерфейс BillingService и электронную карту Card.

Читайте также:  Почему не отправить письмо по электронной почте

Разумнее было бы построить проекты таким образом, чтобы общие java-модули (Card и BillingService) были описаны только один раз в одном из приложений. Это можно было бы сделать, например, с использованием maven. Но в этом случае усложниться процесс описания проектов и, к тому же, (кто знает) будет ли у Вас в будущем при разработке собственного проекта доступ к исходным кодам серверного приложения? Возможно, что в Вашем распоряжении будут только интерфейсы взаимодействия и структуры объектов.

Листинг клиентского класса BillingClient

Класс BillingClient включает методы :

• createCard – создание объекта электронной карты;
• registerCards – регистрации карт;
• addMoney – добавления денежных средств на карты;
• getBalance – чтение остатков средств на картах.

Все вызовы методов интерфейса BillingService обрамлены конструкцией try . catch с перехватыванием исключений типа RemoteException.

В конструкторе класса сначала устанавливается соединение с RMI объектом, после чего последовательно вызываются методы регистрации карт, добавления денежных средств на карты и получения остатков средств на картах. Чтобы найти серверный RMI объект на локальном сервере, устанавливается системное свойство RMI_HOSTNAME (127.0.0.1) и определяется ссылка на объект (SERVICE_PATH) с использованием службы имен и каталогов JNDI (Java Naming and Directory Interface). Поскольку сервер при регистрации RMI объекта использовал порт 1099, то в ссылке порт не указывается.

Сообщения клиентского приложения

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

Сообщения серверного приложения

Серверное приложение выводит в консоль сообщения при вызове методов :

Скачать пример

Исходный коды рассмотренного примера в виде двух проектов Eclipse можно скачать здесь (15.7 Kб). Проекты включают командные bat-файлы для проверки функционирования примера. Для этого достаточно только разместить проекты не диске C: (Windows) и стартовать командный файл сначала сервера, потом клиента.

I have two RMI java applications:

Communication between the two is done with the help of Ngrok:

I think the problem is at

what should I put on the server and client at "java.rmi.server.hostname"?

(Sorry for my bad english)

1 Answer 1

In general its only required on server side to show on what hostname exported stubs will be available to the world.

It is usefull for example, when your server is in the intranet and listens on some interface lets say 192.168.2.1 . NAT proxy can have ports forwarded to that host from internet. Normally RMI registry would report stubs beeing exported on address 192.168.2.1:someport . But obviously you cannot hit that address directly java.rmi.server.hostname comes in action. By setting that property, RMI registry will anounce stubs beeing exported on given hostname insteed on actual intranet address, allowing clients to get to the stubs from outside world trough forwarded ports on NAT gateway.

Читайте также:  Как в ворде сделать повторяющийся колонтитул

So if your server is behind NAT, it should specify the domain that points to your NAT gateway from the Internet. If your server has external IP and its listening on that IP, then this property is not needed.

This is a short blog post about two common pitfalls you should be aware of when using Java RMI.

If you are getting strange Connection refused to host: error messages on the RMI client and you are sure the connection should work (you double checked all the standard things like network configuration etc.) the RMI system property java.rmi.server.hostname is something to look at.

To call a method on a remote object the RMI client has first to retrieve a remote stub object from the RMI registry. This stub object contains the server address that is later used to connect to the remote object when a remote method should be called (the connection to the RMI registry and the connection to the remote object are two completely different things). By default the server will try to detect his own address and pass it to the stub object. Unfortunatelly the algorithm that is used to detect the server address doesn’t always produce a useful result (depending on the network configuration).

It is possible to overr >java.rmi.server.hostname on the RMI server.

This can either be done in Java code

or by adding a Java command line parameter:

Setting RMI service ports

If you have trouble making RMI calls through a firewall you should make sure you set specific ports for remote objects. By default port 1099 used by the RMI registry so make sure you opened this port in the firewall. However, this port is only used by the client to connect to the RMI registry and not for the communication between the stub and the remote object. For the later one random ports are used by default. Since you don’t want to open all ports in your firewall you should set a specific port for RMI remote objects.

This can be done by overr >createServerSocket() method of RMISocketFactory :

By default createServerSocket() chooses a free random port if 0 is passed as parameter. In this modified version of createServerSocket() a specific port ( 1234 ) is returned when 0 is passed as parameter.

If you are using Spring’s RmiServiceExporter you can use the setServicePort() method to export services on a specific port:

Note that multiple remote objects/services can share the same port. After you set a specific port, you just have to open this port in your firewall.

Рекомендуем к прочтению

Добавить комментарий

Ваш адрес email не будет опубликован.