КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Листинг 1.3. Файл header.pas, используемый клиентом и сервером
Примеры клиента и сервера Чтобы внести большую ясность в то, как работают клиент и сервер, в этом пункте мы рассмотрим описание клиента и файлового сервера на языке Pascal. И клиент, и сервер должны совместно использовать некоторые определения, которые мы соберем вместе в файл под названием header.pas, текст которого приведен в листинге 1.3. Эти определения затем включаются в тексты программ клиента и сервера следующей строкой:
uses header.pas;
/* Определения, необходимые и клиентам, и серверам */ Const /* Максимальная длина имени файла */ МАХ_РАТН = 255; /* Максимальное количество данных, передаваемое за один раз */ BUF_SIZE = 1024; /* Сетевой адрес файлового сервера */ FILE_SERVER = 243; /* Определения разрешенных операций */ /* создать новый файл */ OP_CREATE = 1; /* считать данные из файла и вернуть их */ OP_READ = 2; /* записать данные в файл */ OP_WRITE = 3; /* удалить существующий файл */ OP_DELETE = 4; /* Коды ошибок */ /* операция прошла успешно */ OK = 0; /* запрос неизвестной операции */ E_BAD_OPER = -1; /* ошибка в параметре */ E_BAD_PARAM = -2; /* ошибка диска или другая ошибка чтения-записи */ E_IO = –3;
/* Определение формата сообщения */ type TMessage = record source: longint; /* идентификатор источника */ dest: longint; /* идентификатор приемника */ opcode: longint; /* запрашиваемая операция */ count: longint; /* число передаваемых байт */ offset: longint; /* позиция в файле, с которой начинается ввод-вывод */ result: longint; /* результат операции */ name: string[MAX_PATH]; /* имя файла, с которым производятся операции */ data: string [BUF_SIZE]; /* данные, которые будут считаны или записаны */ end;
Итак, перед нами текст файла header.pas. Он начинается с определения двух констант, МАХ_РАТН и BUF_SIZE, которые определяют размер двух массивов, используемых в сообщении. Первая задает число символов, которое может содержаться в имени файла (то есть в строке с путем типа /usr/ast/books/opsys/chapter1.t). Вторая задает размер блока данных, который может быть прочитан или записан за одну операцию путем установки размера буфера. Следующая константа, FILE_ SERVER, задает сетевой адрес файлового сервера, на который клиенты могут посылать сообщения. Вторая группа констант задает номера операций. Они необходимы для того, чтобы и клиент, и сервер знали, какой код представляет чтение, какой код — запись и т. д. Мы приводим здесь только четыре константы, в реальных системах их обычно больше. Каждый ответ содержит код результата. Если операция завершена успешно, код результата обычно содержит полезную информацию (например, реальное число считанных байтов). Если нет необходимости возвращать значение (например, при создании файла), используется значение ОК. Если операция по каким-либо причинам окончилась неудачей, код результата (E_BAD_OPER, E_BAD_PARAM и др.) сообщает нам, почему это произошло. Наконец, мы добрались до наиболее важной части файла header.pas — определения формата сообщения. В нашем примере это структура с 8 полями. Этот формат используется во всех запросах клиентов к серверу и ответах сервера. В реальных системах, вероятно, фиксированного формата у сообщений не будет (поскольку не во всех случаях нужны все поля), но здесь это упростит объяснение. Поля source и dest определяют, соответственно, отправителя и получателя. Поле opcode — это одна из ранее определенных операций, то есть create, read, write или delete. Поля count и offset требуются для передачи параметров. Поле result в запросах от клиента к серверу не используется, а при ответах сервера клиенту содержит значение результата. В конце структуры имеются два массива. Первый из них, name, содержит имя файла, к которому мы хотим получить доступ. Во втором, data, находятся возвращаемые сервером при чтении или передаваемые на сервер при записи данные. Давайте теперь рассмотрим код в листингах 1.4 и 1.5. Листинг 1.4 — это программа сервера, листинг 1.5 — программа клиента. Программа сервера достаточно элементарна. Основной цикл начинается вызовом receive в ответ на сообщение с запросом. Первый параметр определяет отправителя запроса, поскольку в нем указан его адрес, а второй указывает на буфер сообщений, идентифицируя, где должно быть сохранено пришедшее сообщение. Процедура receive блокирует сервер, пока не будет получено сообщение. Когда оно наконец приходит, сервер продолжает свою работу и определяет тип кода операции. Для каждого кода операции вызывается своя процедура. Входящее сообщение и буфер для исходящих сообщений заданы в параметрах. Процедура проверяет входящее сообщение в параметре m1 и строит исходящее в параметре m2. Она также возвращает значение функции, которое передается через поле result. После посылки ответа сервер возвращается к началу цикла, выполняет вызов receive и ожидает следующего сообщения. В листинге 1.5 находится процедура, копирующая файлы с использованием сервера. Тело процедуры содержит цикл чтения блока из исходного файла и записи его в файл-приемник. Цикл повторяется до тех пор, пока исходный файл не будет полностью скопирован, что определяется по коду возврата операции чтения — должен быть ноль или отрицательное число. Первая часть цикла состоит из создания сообщения для операции чтения и пересылки его на сервер. После получения ответа запускается вторая часть цикла, в ходе выполнения которой полученные данные посылаются обратно на сервер для записи в файл-приемник. Программы из листингов 1.4 и 1.5 — это только набросок кода. В них опущено множество деталей. Так, например, не приводятся процедуры do_xxx (которые на самом деле выполняют работу), отсутствует также обработка ошибок. Однако общая идея взаимодействия клиента и сервера вполне понятна. В следующих пунктах мы ближе рассмотрим некоторые дополнительные аспекты модели клиент-сервер.
Дата добавления: 2014-01-13; Просмотров: 435; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |