Э. Таненбаум, М. ван Стеен - Распределённые системы (принципы и парадигмы) (1162619), страница 17
Текст из файла (страница 17)
Поля count и offset требуются для передачи параметров. Поле result в запросах от клиента к серверу не используется, а при ответах сервера клиенту содержит значение результата. В конце структуры имеются два массива. Первыйиз них, name, содержит имя файла, к которому мы хотим получить доступ.
Во втором, data, находятся возвращаемые сервером при чтении или передаваемые насервер при записи данные.Давайте теперь рассмотрим код в листингах 1.4 и 1.5. Листинг 1.4 — это программа сервера, листинг 1.5 — программа клиента. Программа сервера достаточноэлементарна.
Основной цикл начинается вызовом receive в ответ на сообщениес запросом. Первый параметр определяет отправителя запроса, поскольку в немуказан его адрес, а второй указывает на буфер сообщений, идентифицируя, гдедолжно быть сохранено пришедшее сообщение.
Процедура receive блокируетсервер, пока не будет получено сообщение. Когда оно наконец приходит, серверпродолжает свою работу и определяет тип кода операции. Для каждого кода операции вызывается своя процедура. Входящее сообщение и буфер для исходящихсообщений заданы в параметрах. Процедура проверяет входящее сообщениев параметре ml и строит исходящее в параметре т2. Она также возвращает значение функции, которое передается через поле result. После посылки ответа сервер возвращается к началу цикла, выполняет вызов receive и ожидает следующего сообщения.В листинге 1.5 находится процедура, копирующая файлы с использованиемсервера. Тело процедуры содержит цикл чтения блока из исходного файла и записи его в файл-приемник.
Цикл повторяется до тех пор, пока исходный файл небудет полностью скопирован, что определяется по коду возврата операции чтения — должен быть ноль или отрицательное число.Первая часть цикла состоит из создания сообщения для операции чтения и пересылки его на сервер. После получения ответа запускается вторая часть цикла,в ходе выполнения которой полученные данные посылаются обратно на сервердля записи в файл-приемник. Программы из листингов 1.4 и 1.5 — это только набросок кода. В них опущено множество деталей.
Так, например, не приводятсяпроцедуры do_xxx (которые на самом деле выполняют работу), отсутствует такжеобработка ошибок. Однако общая идея взаимодействия клиента и сервера вполне1.5. Модель клиент-сервер71понятна. В следующих пунктах мы ближе рассмотрим некоторые дополнительные аспекты модели клргент-сервер.Листинг 1.4. Пример сервера#1nclucie <heacler.h>void ma1n(vo1ci) {struct message ml. m2:/'^ входящее и исходящее сообщения */1nt r:1'^ код результата */whlle(TRUE) {/* сервер работает непрерывно */receive(FILE_SERVER, &ml): /* блок ожидания сообщения ^/switch(mi.opcode) {/* в зависимости от типа запроса Чcase CREATE:r do_create(&ml. &m2); break:case READ:г do_read(&ml.
&m2) break:case WRITE:г do_wr1te(&ml. &m2): break;case DELETE:г do_delete(&ml. &m2): break:default:гE BAD OPER;m2.result = r:send(m1.sowvz^, &m2):/* вернуть результат клиенту V/* послать ответ */Листинг 1.5. Клиент, использующий сервер из листинга 1.4 для копирования файла#1nclucle <header.h>1'^ процедура копирования файла через сервер •ki1nt copyCchar *src. char *dst)istruct message ml:/* буфер сообщения */long position:/* текущая позиция в файле */long client = 110:/* адрес клиента *//* подготовиться к выполнению */initializeO:position = 0:do {/^ операция чтения */ml.opcode = READ:/^ текущая позиция в файле */ml.offset = position:/^ сколько байт прочитать ^/ml. count = BUFJIZE:/* скопировать имя читаемогоstrcpy(&ml.name, src):файла*//* послать сообщение на файловый сервер*/sendCFILESERVER.
&ml):/* блок ожидания ответа */receiveCclient. &ml):/* Записать полученные данные E файл-приемник. *//* операция: запись */ml.opcode = WRITE:ml.offset = position:/* текущая позиция в файле */ml.count = ml.result:/* сколько байт записать */strcpy(&ml.name, cist):/^ скопировать имя записываемогофайла*//^ послать сообщение на файловый сервер */send(FILE_SERVER. &ml):/* блок ожидания ответа */receive(client. &ml):I-' в ml.result содержитсяposition += ml.result:количество записанных байтов */} whileC ml.result > 0 ):/* повторять до окончания */1'^ вернуть OK или код ошибки */returnCml.result >= 0 ? OK :ml .result):72Глава 1.
Введение1.5.2. Разделение приложений по уровнямМодель клиент-сервер была предметом множества дебатов и споров. Один изглавных вопросов состоял в том, как точно разделить клиента и сервера. Понятно, что обычно четкого различия нет. Например, сервер распределенной базыданных может постоянно выступать клиентом, передающим запросы на различные файловые серверы, отвечающие за реализацию таблиц этой базы данных.В этом случае сервер баз данных сам по себе не делает ничего, кроме обработкизапросов.Однако рассматривая множество приложений типа клиент-сервер, предназначенных для организации доступа пользователей к базам данных, многие рекомендовали разделять их на три уровня.> уровень пользовательского интерфейса;4- уровень обработки;> уровень данных.Уровень пользовательского интерфейса содержит все необходимое для непосредственного общения с пользователем, например для управление дисплеем.Уровень обработки обычно содержит приложения, а уровень данных — собственно данные, с которыми происходит работа.
В следующих пунктах мы обсудим каждый из этих уровней.Уровень пользовательского интерфейсаУровень пользовательского интерфейса обычно реализуется на клиентах. Этотуровень содержит программы, посредством которых пользователь может взаимодействовать с приложением. Сложность программ, входящих в пользовательскийинтерфейс, весьма различна.Простейший вариант программы пользовательского интерфейса не содержитничего, кроме символьного (не графического) дисплея.
Такие интерфейсы обычно используются при работе с мэйнфреймами. В том случае, когда мэйнфреймконтролирует все взаимодействия, включая работу с клавиатурой и монитором,мы вряд ли можем говорить о модели клиент-сервер. Однако во многих случаяхтерминалы пользователей производят некоторую локальную обработку, осуществляя, например, эхо-печать вводимых строк или предоставляя интерфейсформ, в котором можно отредактировать введенные данные до их пересылки наглавный компьютер.В наше время даже в среде мэйнфреймов наблюдаются более совершенныепользовательские интерфейсы. Обычно на клиентских машинах имеется как минимум графический дисплей, на котором можно задействовать всплывающие иливыпадающие меню и множество управляющих элементов, доступных для мышиили клавиатуры.
Типичные примеры таких интерфейсов — надстройка X-Windows, используемая во многих UNIX-системах, и более ранние интерфейсы, разработанные для персональных компьютеров, работающих под управлением MSDOS и Apple Macintosh.1.5. Модель клиент-сервер73Современные пользовательские интерфейсы значительно более функциональны. Они поддерживают совместную работу приложений через единственное графическое окно и в ходе действий пользователя обеспечивают черезэто окно обмен данными.
Например, для удаления файла часто достаточноперенести значок, соответствующий этому файлу, на значок мусорной корзины. Аналогичным образом многие текстовые процессоры позволяют пользователю перемегцать текст документа в другое место, пользуясь только мышью. Мы вернемся к пользовательским интерфейсам в главе 3.Уровень обработкиМногие приложения модели клиент-сервер построены как бы из трех различныхчастей: части, которая занимается взаимодействием с пользователем, части, которая отвечает за работу с базой данных или файловой системой, и средней части,реализующей основную функциональность приложения.
Эта средняя часть логически располагается на уровне обработки. В противоположность пользовательским интерфейсам или базам данных на уровне обработки трудно выделить общие закономерности. Однако мы приведем несколько примеров для разъяснениявопросов, связанных с этим уровнем.В качестве первого примера рассмотрим поисковую машину в Интернете.Если отбросить все анимированные баннеры, картинки и прочие оконные украшательства, пользовательский интерфейс поисковой машины очень прост: пользователь вводит строку, состоящую из ключевых слов, и получает список заголовков web-страниц.
Результат формируется из гигантской базы просмотренныхи проиндексированных web-страниц. Ядром поисковой машины является программа, трансформирующая введенную пользователем строку в один или несколько запросов к базе данных. Затем она помещает результаты запроса в список и преобразует этот список в набор HTML-страниц. В рамках модели клиентсервер часть, которая отвечает за выборку информации, обычно находится науровне обработки. Эта структура показана на рис. 1.19.Пользовательскийинтерфейсle /Выражениес ключевыми /словами /ГенераторзапросовЗапросык базе данныхБаза данныхweb-страницУровеньпользовательскогоинтерфейсаHTML-страницач со спискомГенераторHTML-страницУровеньУпорядоченный обработкисписокзаголовковКомпонентстраницупорядочиванияЗаголовки web-страницс метаинформациейРис. 1.19. Обобщенная организация трехуровневой поисковой машины для Интернета74Глава 1.
ВведениеВ качестве второго примера рассмотрим систему поддержки принятия penieний для фондового рынка. Так же как PI В ПОИСКОВОЙ машине, эту систему можноразделР1ть на внепрнрпр ригтерфейс, реалргзующий работу с пользователем, внутренрпою часть, отвечающую за доступ к базе с финансовор! информацией, PI промежуточную программу анализа. Анализ финансовых данных может потребоватьзамысловатых методик и технологий на основе статистических методов и искусственного интеллекта.
В некоторых случаях для того, чтобы обеспечить требуемые производительрюсть и время отклика, ядро системы поддержки финансовыхрешений должно выполняться на высокопроизводительных компьютерах.Нашим последнихм примером будет типичный офисный пакет, состоя1ций изтекстового процессора, приложения для работы с электронными таблицами, коммуникационных утилит и т. д. Подобные офисные пакеты обычно поддерживаютобобщенный пользовательский интерфейс, возможность создания составных документов и работу с файлами в домашнем каталоге пользователя.