div.main {margin-left: 20pt; margin-right: 20pt}Простое CORBA приложение - своими руками.
Технология CORBA - это стандарт написания распределенных приложений,
предложенный консорциумом OMG (Open Management Group). Создавая CORBA-объекты,
мы можем ,например, существенно уменьшить время решения задач, требующих
выполнения большого объема вычислений. Это возможно благодаря размещению
CORBA-объектов на разных машинах. Каждый удаленный объект решает определенную
подзадачу, тем самым разгружает клиент от выполнения лишней работы.
Рассмотрим взаимодействие объектов в архитектуре CORBA
Рис.1 Взаимодействие объектов в архитектуре CORBA
Основу CORBA составляет объектный брокер запросов (Object Request Broker).
ORB управляет взаимодействием объектов в распределенной сетевой среде. IIOP
(Internet Inter-ORB Protocol) - это специальный протокол взаимодействия между
ORB.
В адресном пространстве клиента функционирует специальный объект, называемый
заглушкой (stub). Поучив запрос от клиента, он упаковывает параметры запроса в
специальный формат и передает его серверу, а точнее скелету.
Скелет (skeleton) – объект, работающий в адресном пространстве сервера.
Получив запрос от клиента, он распаковывает его и передает серверу. Также скелет
преобразует ответы сервера и передает их клиенту (заглушке).
Для того, чтобы написать любое приложение CORBA используя технологию Java,
необходимо иметь две вещи – это установленный пакет JDK1.2 и компилятор
idltojava. JDK предоставляет набор классов для работы с
CORBA объектами, а idltojava производит отображение языка
IDL в Java.
Создание CORBA приложения на Java начинается с написания интерфейса для
удаленного объекта, используя язык описания интерфейсов (Interface Definition
Language, IDL).
Создадим файл test.idl module testApp {
interface test
{
long count(in string msg);
};
};
Данный интерфейс описывает лишь один метод count. Причем, нам не
важно, что делает этот метод, главное мы определяем, что он есть, определяем
какие у него входные и выходные параметры.
Воспользуемся компилятором idltojava. idltojava Hello.idlПримечание. Данный компилятор по
умолчанию использует препроцессор языка С++, поэтому что бы не мучится с
сообщением об ошибке имя команды или файла указано неправильно (в
переменной окружения CPP должен быть прописан путь к нему) отключим его
использование, установив флаги. idltojava –fno-cpp Hello.idl
Результат работы данной программы можно представить в виде
схемы.
Рис.2 Работа idltojava компилятора
В текущей директории появилась новая папка testApp, в которой
содержатся пять java – файлов. Каждый из них имеет свое назначение.
_testImplBase.java – абстрактный класс, который представляет собой не
что иное, как скелет сервера (skeleton) и обеспечивает функциональность сервера;
_testStub.java – класс, реализующий заглушку (stub) клиента.
Обеспечивает функциональность клиента;
test.java – класс, содержащий описание интерфейса test на языке Java;
testHelper.java и testHolder.java – классы, предоставляющие
вспомогательные функции для CORBA объектов.
Теперь наша задача – написать класс, реализующий интерфейс test. Такие
классы должны называться так, чтобы в их имени было слово “Servant”, в нашем
случае это будет testServant. class testServant extends _testImplBase
{
public int count(String msg)
{
return msg.length();
}
}
Обратите внимание, что этот класс унаследован от _testImplBase. Как
видно, здесь реализован метод count, который в данном примере считает количество
букв в принятом сообщении.
Теперь перейдем непосредственно к написанию серверной части приложения.
Первое что мы делаем, создаем ORB. Затем создаем экземпляр класса удаленного
объекта (testServant) и регистрируем его в ORB. Дальше вызываем специальную
службу имен (NameService) и регистрируем в ней имя удаленного объекта, чтобы
клиент смог его найти (есть и другой способ нахождения удаленного объекта, но о
нем чуть позже).
Рассмотрим подробнее эти этапы.
Создание и инициализация ORB. Производится вызовом статического метода
init класса ORB
ORB orb = ORB.init();
Создание экземпляра класса удаленного объекта и регистрация его в ORB
testServant testRef = new testServant();
orb.connect(testRef);
Получение контекста имен (NamingContext)
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
в первой строчке мы получаем объектую ссылку на службу имен (NameService).
Но фактически это обыкновенный CORBA-объект и для того, чтобы использовать его
как контекст имен (NamingContext), необходимо вызвать метод narrow
класса NamingContextHelper, который как бы конкретизирует данный
CORBA-объект.
Регистрация имени удаленного объекта (testServant)
Как было сказано раньше регистрация имени производится для того чтобы
клиент смог найти удаленный объект. Этой цели служит функция
rebind(NameComponent[] nc, Object obj) интерфейса NamingContext. NameComponent nc = new NameComponent("test", "");
//первый параметр
//указывает имя объекта,
//второй нам использовать не обязательно
NameComponent path[] = {nc};
ncRef.rebind(path, testRef);
Ожидание запросов от клиента. java.lang.Object sync = new java.lang.Object();
synchronized (sync) {
sync.wait();
}
После того как сервер обработает запрос от клиента и выполнит метод
count он снова перейдет в состояние ожидания.
Теперь сервер готов к работе
Листинг 1. testServer.java import testApp.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.lang.*;
class testServant extends _testImplBase
{
public int count(String msg)
{
return msg.length();
}
}
public class testServer {
public static void main(String args[])
{
try
{
ORB orb = ORB.init(args, null);
testServant testRef = new testServant();
orb.connect(testRef);
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef =
NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("test", "");
NameComponent path[] = {nc};
ncRef.rebind(path, testRef);
java.lang.Object sync = new java.lang.Object();
synchronized (sync) {
sync.wait()
}
}
catch (Exception e) {
System.err.println("ERROR: " + e);
e.printStackTrace(System.out);
}
}
}
Обратите внимание на то, что все операции выполняемые над CORBA-объектами
заключены в try-catch блок.
Перейдем к написанию кода для клиента.
Основные шаги написания клиентского приложения
Создание и инициализация ORB
Получение контекста службы имен (NamingContext)
Нахождение удаленного объекта
Вызов метода count.
Как видно, первые два пункта совпадают с этапами создания серверного
приложения, поэтому рассматривать их не будем.
Третий пункт реализуется тоже достаточно просто. Создается объект
NameComponent. Вызывается метод resolve(NameComponent[] path),
который отыскивает по имени удаленный объект (стандартный CORBA-объект). При
помощи метода narrow(org.omg.CORBA.Object obj) класса testHelper
(сгенерированного idltojava компилятором) получаем объектную ссылку на
интерфейс test. NameComponent nc = new NameComponent("test", "");
NameComponent path[] = {nc};
org.omg.CORBA.Object obj= ncRef.resolve(path);
test testRef = testHelper.narrow(obj);
Теперь можно вызывать метод count String msg = "try to count";
int count = testRef.count(msg);
Листинг 2. testClient.java import testApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.lang.*;
public class testClient
{
public static void main(String args[])
{
try
{
ORB orb = ORB.init(args, null);
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef =
NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("test", "");
NameComponent path[] = {nc};
test testRef =
testHelper.narrow(ncRef.resolve(path));
String msg = "try to count";
int count = testRef.count(msg);
System.out.println
(“number of chars in message is:” + count);
}
catch (Exception e)
{
System.out.println("ERROR : " + e) ;
e.printStackTrace(System.out);
}
}
}
Запуск приложения
Запуск сервера имен (входит в поставку с JDK1.2). Это делается, чтобы мы
смогли получить ссылку на службу имен tnameserv
по умолчанию сервер запускается по порту 900. Это значение можно изменить,
указав параметр запуска -ORBInitialPort, например tnameserv –ORBInitialPort 1024
Запуск сервера testServer java testServer –ORBInitialPort 1024
// указывается тот порт
//по которому работает сервер имен
Запуск клиента testClient java testClient
–ORBInitialHost javas.stu.neva.ru
–ORBInitialPort 1024
параметр -ORBInitialHost указывает хост на котором работает
testServer
после выполнения этого приложения, на консоль будет выведено number of chars in message is:12
Соединение с сервером без использования службы имен
Основная идея этого метода состоит в том, что сервер сохраняет экземпляр
класса удаленного объекта (testServant) в виде текстового файла в любом
месте, доступном клиенту. Клиент загружает из файла данные (в объект
String) и преобразует специальными методами в объектную ссылку на
удаленный объект.
Все это реализуется следующим образом
Удалим некоторую часть кода – это касается и клиента (testServer.java
и testClient.java)
Исключим из import библиотеки org.omg.CosNaming.*;
org.omg.CosNaming.NamingContextPackage.*;
Удалим код соответствующий п.3-п.4Вместо удаленного кода вставим –
для сервера: //преобразуем объект в строку
String ior = orb.object_to_string(testRef);
String filename = System.getProperty("user.home") +
System.getProperty("file.separator")+"test_file";
//создаем файл test_file
FileOutputStream fos = new FileOutputStream(filename);
PrintStream ps = new PrintStream(fos);
//записываем в него данные
ps.print(ior);
ps.close();
для клиента: String filename = System.getProperty("user.home") +
System.getProperty("file.separator")+"test_file";
//открываем файл
FileInputStream fis = new FileInputStream(filename);
DataInputStream dis = new DataInputStream(fis);
//читаем данные
String ior = dis.readLine();
//преобразуем в объект CORBA
org.omg.CORBA.Object obj = orb.string_to_object(ior);
//получаем ссылку на удаленный объект
test testRef = testHelper.narrow(obj);
Скомпилируем приложения, запустим сервер и клиент аналогично тому, как мы
делали это раньше (сервер имен запускать в данном случае не надо).
Автор: Александр Годин, E-Mail: alexgoldd@mail.ru
|