
- •Введение
- •1 Тема 1. Введение в теорию вычислительных сетей
- •1.1 Общая классификация систем обработки данных
- •1.1.1 Сосредоточенные системы
- •1.1.2 Распределенные системы
- •1.1.3 Распределенные вычислительные сети
- •1.2 Сетевые объектные системы
- •1.2.1 Классические приложения модели OSI
- •1.2.2 Распределенная вычислительная среда (DCE)
- •1.2.3 Технология CORBA
- •1.2.4 Удаленный вызов методов
- •1.3 Сервис-ориентированные технологии
- •1.3.1 Функции и сервисы
- •1.3.2 Системы midlleware
- •1.3.3 Сервисные шины предприятий
- •1.4 Виртуальные системы
- •1.4.1 Виртуальные машины
- •1.4.2 Виртуализация вычислительных комплексов на уровне ОС
- •1.4.2 Виртуализация ПО на уровне языка
- •1.4.3 Виртуальная машина языка Java
- •1.5 Итоги теоретических построений
- •Вопросы для самопроверки
- •2 Тема 2. Инструментальные средства языка Java
- •2.1 Общее описание инструментальных средств языка
- •2.1.1 Инструментальные средства командной строки
- •2.1.2 Пакетная организация языка Java
- •2.1.3 Инструментальные средства Eclipse
- •2.2 Классы и простые типы данных
- •2.2.1 Операторы и простые типы данных
- •2.2.2 Синтаксис определения классов
- •2.2.3 Синтаксис и семантика методов
- •2.2.4 Синтаксис определения интерфейсов
- •2.2.5 Объекты и переменные
- •2.3 Управляющие операторы языка
- •2.4 Потоки ввода-вывода
- •2.4.1 Стандартный ввод-вывод
- •2.4.2 Классы потоков ввода
- •2.4.3 Классы потоков вывода
- •2.5 Управление сетевыми соединениями
- •2.5.1 Адресация на базе класса InetAddress
- •2.5.2 Адресация на базе URL и URLConnection
- •2.5.3 Сокеты протокола TCP
- •2.5.4 Сокеты протокола UDP
- •2.5.5 Простейшая задача технологии клиент-сервер
- •2.6 Организация доступа к базам данных
- •2.6.1 Инструментальные средства СУБД Apache Derby
- •2.6.2 SQL-запросы и драйверы баз данных
- •2.6.3 Типовой пример выборки данных
- •Вопросы для самопроверки
- •3 Тема 3. Объектные распределенные системы
- •3.1 Брокерные архитектуры
- •3.1.1 Вызов удаленных процедур
- •3.1.2 Использование удаленных объектов
- •3.2 Технология CORBA
- •3.2.1 Брокерная архитектура CORBA
- •3.2.2 Проект серверной части приложения NotePad
- •3.2.3 Проект клиентской части приложения Example12
- •3.2.4 Генерация распределенного объекта OrbPad
- •3.2.5 Реализация серверной части ORB-приложения
- •3.2.6 Реализация клиентской части ORB-приложения
- •3.3 Технология RMI
- •3.3.1 Интерфейсы удаленных объектов
- •3.3.2 Реализация RMI-сервера
- •3.3.3 Реализация RMI-клиента
- •Вопросы для самопроверки
- •4 Тема 4. Web-технологии распределенных систем
- •4.1 Общее описание технологии web
- •4.1.1 Унифицированный идентификатор ресурсов (URI)
- •4.1.2 Общее представление ресурсов (HTML)
- •4.1.3 Протокол передачи гипертекста (HTTP)
- •4.2 Модели «Клиент-сервер»
- •4.2.1 Распределение приложений по уровням
- •4.3 Технология Java-сервлетов
- •4.3.1 Классы Servlet и HttpServlet
- •4.3.2 Контейнер сервлетов Apache Tomcat
- •4.3.3 Диспетчер запросов - RequestDispatcher
- •4.3.4 Технология JSP-страниц
- •4.3.5 Модель MVC
- •Вопросы для самопроверки
- •5 Тема 5. Сервис-ориентированные архитектуры
- •5.1 Концепция SOA
- •5.1.1 Связывание распределенных программных систем
- •5.1.2 Web-сервисы первого и второго поколений
- •5.1.3 Брокерные архитектуры web-сервисов
- •5.2 Частные подходы к реализации сервисных технологий
- •5.2.1 Технологии одноранговых сетей
- •5.2.2 Технологии GRID
- •5.2.3 Облачные вычисления и «виртуализация»
- •Вопросы для самопроверки
- •Список использованных источников
- •Алфавитный указатель
144
серверу имен и получать от него координаты доступа к RmiPadServer. Все это скрыто внутри технологии RMI, требует знания основ администрирования сетей ЭВМ и обсуждается на лабораторных и практических занятиях.
3.3.3 Реализация RMI-клиента
Принципиально, клиентскую программу для нашего примера можно было бы реализовать в проекте сервера, но, для убедительности, мы создадим ее в новом проекте proj13.
Сначала, в проекте создадим файл интерфеса с именем RmiPad и перенесем в него содержимое файла RmiPad.java из проекта proj12. Это необходимо для того, чтобы клиентская программа могла работать с описанием интерфейса удаленного объекта.
Затем, в проекте proj13 создадим класс с именем RmiPadClient и пакетным префиксом asu.rmiclient, а первоначальное содержимое его скопируем из класса OrbPadClient проекта proj11, в котором уже реализовано приложение клиента, но для технологии CORBA.
После необходимых изменений, мы получим приложение RMI-клиента, показанное на листинге 3.9.
Листинг 3.9 — Исходный текст клиента RmiPadClient из среды Eclipse EE
package asu.rmiclient;
import java.io.IOException; import java.rmi.Naming; import asu.rvs.rmi.RmiPad;
/**
*Реализация клиента распределенного объекта RmiPad
*@author vgr
*/
public class RmiPadClient {
/**
*Метод чтения целого числа со стандартного ввода
*@return целое число или -1, если - ошибка.
*/
public int getKey()
{
int ch1 = '0'; int ch2 = '9'; int ch; String s = "";
try
{
while(System.in.available() == 0) ;
while(System.in.available() > 0)
{
ch = System.in.read();
if (ch == 13 || ch < ch1 || ch > ch2)
145
continue; if (ch == 10)
break;
s += (char)ch;
};
if (s.length() <= 0) return -1;
ch = new Integer(s).intValue(); return ch;
}
catch (IOException e1)
{
System.out.println(e1.getMessage()); return -1;
}
}
/**
*Метод чтения строки текста со стандартного ввода
*@return строка текста.
*/
public String getString()
{
String s = "\r\n"; String text = ""; int n;
char ch; byte b[];
try
{
//Ожидаем поток ввода while(System.in.available() == 0) ; s = "";
while((n = System.in.available()) > 0)
{
b = new byte[n]; System.in.read(b); s += new String(b);
};
//Удаляем последние символы '\n' и '\r' n = s.length();
while (n > 0)
{
ch = s.charAt(n-1);
if (ch == '\n' || ch == '\r') n--;
else
break;
}
//Выделяем подстроку
if (n > 0)
text = s.substring(0, n);
else
text = ""; return text;
}
catch (IOException e1)
146
{
System.out.println(e1.getMessage()); return "Ошибка...";
}
}
public static void main(String[] args)
{
System.out.println( |
|
|||
|
"RmiPadClient для работы с удаленным объектом RmiPad.\n" |
|||
+ |
"\t1) |
если |
ключ - пустой, |
то завершаем программу;\n" |
+ |
"\t2) |
если |
текст - пустой, |
то удаляем по ключу;\n" |
+"\t3) если текст - не пустой, то добавляем его.\n"
+"Нажми Enter - для продолжения ...\n"
+ "----------------------------------------- |
"); |
// Создаем объект локального класса RmiPadClient rpc =
new RmiPadClient(); rpc.getKey();
try{
//Получаю и печатаю список всех регистраций. String[] sss =
Naming.list("//localhost:1099/RmiPad"); for(int i=0; i<sss.length; i++)
System.out.println(sss[i]);
//Получаю объектную ссылку на удаленный объект RmiPad rmipad =
(RmiPad)Naming.lookup("//localhost:1099/RmiPad");
/** * Основной цикл приложения */
int ns; // Число прочитанных строк int nb; // Число прочитанных байт String text, s; // Строка введенного текста String[] ls;
// Цикл обработки запросов |
|
while(true) |
|
{ |
|
//Печатаем заголовок ответа |
|
System.out.println( |
|
"---------------------------------------- |
\n" |
+ "Ключ\tТекст\n" |
|
+ "---------------------------------------- |
"); |
ls = rmipad.getList(); |
|
//Выводим (построчно) результат запроса к БД |
|
ns = 0; |
|
nb = ls.length; |
|
while(ns < nb){ |
|
System.out.println(ls[ns] + "\n"); |
|
ns++; |
|
} |
|
// Выводим итог запроса |
|
System.out.println( |
|
"---------------------------------------- |
\n" |
147
+"Прочитано " + ls.length + " строк\n"
+"----------------------------------------\n"
+"Формируем новый запрос!");
System.out.print("\nВведи ключ |
или Enter: "); |
||
nb = rpc.getKey(); |
|
|
|
if (nb == -1) |
|
|
|
break; |
// |
Завершаем работу программы |
System.out.print("Строка текста или Enter: "); s = rpc.getString();
text = s;
while (s.length() > 0)
{
System.out.print("Строка текста или Enter: "); s = rpc.getString();
if(s.length() <= 0) break;
text += ("\n" + s);
}
if (text.length() <= 0)
{
ns = rmipad.setDelete(nb); if (ns == -1)
System.out.println("\nОшибка удаления строки !!!");
else
System.out.println("\nУдалено " + ns + " строк...");
}
else
{
ns = rmipad.setInsert(nb, text); if (ns == -1)
System.out.println("\nОшибка добавления строки !!!");
else
System.out.println("\nДобалено " + ns + " строк...");
}
System.out.println("Нажми Enter ..."); rpc.getKey();
}
System.out.println("Программа завершила работу...");
}
catch (Exception e)
{
System.out.println("ERROR : " + e) ;
}
}
}
Основное отличие приведенного листинга от текста ORB-клиента (см. листинг 3.6) заключается в том, что RMI-клиент подключает интерфейс удаленного объекта всего лишь одним методом lookup() класса Naming:

148
// Получаю объектную ссылку на удаленный объект RmiPad rmipad =
(RmiPad)Naming.lookup("//localhost:1099/RmiPad");
все остальные изменения связаны только с различными типами разных технологий и приложений.
Запустив на выполнение программу RMI-клиента, можно убедиться в ее работоспособности, как показано на рисунке 3.22.
Рисунок 3.22 — Начало диалога приложения RmiPadClient
3.3.4Завершение реализации RMI-проекта
Взавершении данного подраздела необходимо реализовать и протестировать наше распределенное приложение в виде двух Jar-архивов: rmipadserver.jar
иrmipadclient.jar. Для этого, предварительно нужно:
•в среде разработки Eclipse EE: остановить работу RMI-клиента, а затем — RMI-сервера;
•в виртуальном терминале остановить работу сервера rmiregistry.
Сначала, проведем архивацию и тестирование серверной части RMI-проек-
та. Для этого, выделим в Eclipse EE проект с именем proj12 и проведем создание архива, как это уже было описано в пункте 3.2.2 данной главы. Сам архив сохраним в файле с абсолютным путом доступа: $HOME/lib/rmipadserver.jar.
Теперь отредактируем переменную среды CLASSPATH, как это показано на рисунке 3.23, чтобы rmiregistry мог найти архив сервера.
Рисунок 3.23 — Редактирование .bashrc для архива RMI-сервера

149
Сохранив изменения в файле .bashrc, запустим новый виртуальный терминал, в котором стартуем сервер rmiregistry. Затем, перейдя в каталог $HOME/lib/, запустим сервер как показано на рисунке 3.24.
Рисунок 3.24 — Запуск RMI-сервера из архива rmipadserver.jar
Хорошо видно, что сервер стартовал — нормально, но здесь надо отметить, что если бы мы не внесли изменения в файл .bashrc, то rmiregistry регистрировал бы приложение, размещенное в проекте proj12 среды Eclipse EE.
Запустив нормально RMI-серверб следует провести:
•тестирование RMI-клиента в среде Eclipse EE;
•создание архива проекта proj13 и размещение его в каталоге $HOME/lib/;
•переход в каталог $HOME/lib/ и запуск RMI-клиента, как это показано на рисунке 3.25.
Тестирование распределенного приложения можно продолжить, запуская приложение RMI-клиента на множестве виртуальных терминалов командами:
java -jar rmipadclient.jar
каждое отдельно запущенное приложение клиента будет работать самостоятельно, но с единой базой данных.
На этом, мы завершаем изучение технологии RMI и всей темы, посвященной объектным распределенным системам. На рисунке 3.26 представлен список и размеры всех созданных в данной главе Jar-архивов приложений. В целом, они посвящены решению одной задачи: ведению записей в таблице notepad базы данных exampleDB, поддерживаемой встроенным вариантом СУБД Apache Derby. Общая методика их реализации отражает общие правила проектирования:
•первоначально создается локальный вариант решения задачи, предполагающий будущее разделение на клиентскую и серверную части; такими части реализованы в архивах notepad.jar и example12.jar;
•решение этой задачи средствами технологии CORBA представлена архивами orbpadserver.jar и orbpadclient.jar;
•решение этой задачи средствами технологии CORBA представлена архивами rmibpadserver.jar и rmipadclient.jar.

150
Рисунок 3.25 — Запуск RMI-клиента из архива rmipadclient.jar
Рисунок 3.26 — Сравнительные размеры созданных Jar-архивов приложений