Программирование >>  Структура ядра и системные вызовы 

1 ... 61 62 63 [ 64 ] 65 66 67 ... 98


/* передать команды О, 1, 2 серверу */

for (int cmd=0; cmd < 3; cmd++)

/* сформировать команду для сервера */ sprintf(buf, %d ,cmd);

if (sp.write(buf,strlen(buf)+1) < 0) return 9;

/* выйти из цикла, если это команда QUIT CMD */ if (cmd==QUIT CMD) break;

I* прочитать ответ сервера */

if (sp.read(buf,sizeof buf) < 0) return IG;

cerr client: recv buf \n ;

sp.shutdown 0 ; return 0;

Синтаксис этой программы-клиента такой же, как в примере программы sock stream.cls. С. Она точно так же создает потоковое гнездо и соединяет его с серверным гнездом. После организации гнезда клиент передает серверу следующие запросы на обслуживание: сообщить дату и местное время; сообщить дату и время по Гринвргчу; выполнить команду завершения работы сервера. Затем клиент читает завершающее сообщение сервера.

После отправки каждой команды (кроме QUIT CMD) на обслуживание клиент принимает ответ сервера и направляет результаты на стандартный вывод. Завершает свою работу программа-клиент после того, как пошлет серверу команду QUITCMD.

Программа-клиент и программа-сервер компилируются следующим образом:

% СС -о soc)c msg srv soc)c msg srv.C -lsoc)cet -Insl % CC -о soc)c msg cls soc)c msg cls.С -lsoc)cet -Insl

Вот примерный протокол взаимодействия этих программ:

% soclc msg srv О fruit & [1] 441

Socket port: 32792

% sock msg cls 32792 fruit

client: recv Sun Feb 12 00:41:25 1997

client: recv Sun Feb 12 08:41:25 1997

[1] + Done sock msg srv 0 fruit

В приведенном выше примере клиентский и серверный процессы взаимодействуют друг с другом с помощью потоковых гнезд домена Internet. Клиент читает только те сообщения сервера, которые тот посылает в ответ на команды LOCAL TIME и UTC TIME. Процессы, использующие гнезда домена Internet, могут работать и на отдельных машинах.

В следующем примере показано, как те же самые процессы взаимодействуют с помощью гнезд домена UNIX:

% sock msg srv SOCK MSG & [1] 446

% sock msg cls SOCK MSG client: recv Sun Feb 12 00:42:38 1997 client: recv Sun Feb 12 08:42:38 1997 [1] + Done sock msg srv SOCK MSG

11.4. Интерфейс транспортного уровня (TLI)

Интерфейс транспортного уровня (Transport Level Imerface, TLI) был разработан в рамках ОС UNIX System V.3 в качестве альтернативы гнездам. TLI более гибок, чем гнезда, и построен на основе механизма STREAMS, поддерживающего большинство транспортных протоколов. TLI создает конечные точки транспортировки (transport endpoirts), поведение и функции которых похожи на поведение и функции гнезд. Например, эти конечные точки транспортировки могут взаимодействовать друг с другом как в режиме с установлением соединения, так и в режиме без установления соединения. Кроме того, процессы, работающие на разных машинах или на одной машине, могут общаться между собой, используя свои конечные точки транспортировки. И гнезда, и конечные точки TLI обозначаются дескрипторами. Процесс может установить для этих дескрипторов флаг 0 NON-BLOCK либо при их назначении, либо при вызове функции fcntl. Это приводит к тому, что соответствующие операции с гнездами и конечными точками TLI выполняются в неблокирующем режиме.

Конечная точка TLI не может взаимодействовать с гнездом. Когда такая точка создается, пользователь должен указать транспортный протокол, который с ней должен быть связан. При создании гнезда указывать транспортный протокол пользователю не приходится. API socket выбирает протокол по умолчанию на основании типа гнезда. Помимо этих различий, есть еще одно: адрес, назначаемый гнезду для внутримашинной связи, отличается от соответствующего адреса конечной точки TLI. Конечной точке TLI для связи с другими конечными точками транспортировки присваивается целочисленный номер порта, тогда как гнезду для работы в таком режиме присваивается путевое UNIX-имя.

В ходе проведения сеанса связи по Internet конечной точке TLI присваивается хост-имя и номер порта (аналогично тому, как это делается для гнезда). При связи с установлением соединения адреса клиентским гнездам присваиваются только в том случае, если клиентские процессы назначают эти адреса явно. Конечным точкам транспортировки адреса присваиваются всегда - либо пользователями, либо базовым транспортным протоколом.

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



интерфейсов прикладного программирования TLI и проводится их сравнение с API гнезд. В последующих разделах более подробно описываются синтаксис и методика использования этих API. В последних двух разделах приведены два примера ТЫ-приложений. Одно из них является вариантом представленной в разделе 11.2 программы типа клиент/сервер, в которой вместо гнезд применяются конечные точки ТЫ. Во втором примере показано, как с помощью конечных точек транспортировки можно посылать дейтаграммные сообщения.

11.4.1. API интерфейса транспортного уровням

Системные функции ТЫ и их назначение описаны ниже. API TLI Назначение

t open Создает конечную точку транспортировки и задает базовый транс-

портный протокол

t bind Присваивает имя конечной точке транспортировки. Для конечной

~ точки, ориентированной на установление соединения, указывается

также максимально допустимое количество запросов на соединение

t listen Ожидает запроса на соединение от клиентской конечной точки

транспортировки

t accept Принимает запрос на соединение от клиентской конечной точки ~ транспортировки

t connect Посылает запрос на соединение в серверную конечную точку транспортировки

t snd Посылает сообщение в конечную точку, с которой уже установлено

~ соединение. Применяется только для конечной точки транспорти-

ровки, ориентированной на соединение

t rcv Принимает сообщение из конечной точки, с которой уже установ-

лено соединение. Применяется только для конечной точки транспортировки, ориентированной на соединение

t snd udata Посылает дейтаграммное сообщение в конечную точку транспортировки с заданным адресом

t rcvudata Принимает из конечной точки транспортировки дейтаграммное сообщение и адрес отправителя

t snddis Разрывает соединение

t rcvdis Возвращает признак разрыва соединения и сообщает, почему оно было разорвано

t sndrel Посылает в конечную точку транспортировки запрос на прекращение передачи через эту точку

t rcvrel Возвращает из конечной точки транспортировки, с которой установлено соединение, признак того, что прием сообщений через эту точку осуществляться не будет

t error Действует аналогично функции perror. В случае неудачного заверше-

ния вызова TLI-функции выводит на экран сообщение об ошибке

API ТУ

Назначение

t alloc Вьщеляет динамическую память для конечной точки транспортиров1ш

t free Освобождает динамическую память, выделенную конечной точке

~ транспортировки

t close Освобожцает дескриптор конечной точки транспортировки

Последовательность вызова описанных API ТЫ при установлении соединения между сервером и клиентом с использованием виртуального канала представлена на рис. 11.3.

Серверная конечная точка транспортировки

t open t bind

Клиентская конечная точка транспортировки

t open

t bind

t listen

t connect

t accept

t snd

t snd t rev

t rev



t sndrel

t rcvrel t close

t rcvrel t sndrei, t close

Рис. U.S. Последовательность вызовов API TLI для серверной и клиентской конечных точек транспортировки

Обратите внимание на сходство этих последовательностей с теми, которые изображены на рис. 11.1. В частности, API t open похож на API socket, API t bind - на API bind, a функции t snd и t rcv - на API send и rev. При Этом, однако, API tjisten - не то же самое, что API listen. API listen задает максимально допустимое для гнезда число ожидающих своей очереди запросов на соединение. Для конечной точки транспортировки эта информация задается в API tjbind. API tjisten очень похож на API гнезд accept: он заставляет процесс ждать клиентского запроса на соединение. После получения



такого запроса функция tjisten возвращает адрес клиентской конечной точки транспортировки. Сервер может вызвать либо функцию t accept - для установления соединения, либо функцию tjsnddis - для разрыва соединения.

Как и API accept, API taccept назначает конкретной конечной точке транспортировки дескриптор, необходимый серверу для установления связи с клиентским процессом. Серверный процесс может продолжать мониторинг последующих запросов на соединение, поступающих из клиентских процессов, используя для этого дескриптор, полученный в результате вызова функции tjopen.

Когда серверный и клиентский процессы заканчивают взаимодействие, один из них может вызвать функцию tjsndrel, которая пошлет процессу-партнеру уведомление о разъединении. Этот партнер вызовет функцию t rcvrel для приема уведомления и ответит посредством вызова функции t sndrel. После получения первым процессом ответного уведомления (в результате вызова функции t rvcret) соединение между конечными точками транспортировки будет разорвано и оба процесса смогут вызвать функцию tjclose, чтобы удалить свои конечные точки транспортировки.

В качестве альтернативы функциям tjsndrel и tj-cvrel серверный и клиентский процессы могут вызвать для разрыва соединения функции t snddis и tj-cvdis. Функция tjsnddis используется для аварийного разрыва соединения: все данные, еще не переданные через конечные точки транспортировки, немедленно уничтожаются. Функция t sndrel используется для неаварийного разрыва соединения: все неотправленные данные доставляются по назначению и лишь после этого соединение разрывается. Все транспортные протоколы, используемые с ТЫ, должны поддерживать функции t snddisvi t rcvdis, тогда как требование о поддержке функций tjsndrel и tj-cwel не является обязательным.

Последовательность вызовов API ТЫ, предназначенных для создания дейтграммной конечной точки транспортировки, приведена на рис. 11.4.

t open

t bind У

t sndudata t rcvudata

t close

Рис. 11.4. Последовательность вызовов API ТЫ для создания дейтаграммной конечной точки транспортировки

Манипулировать дейтаграммными конечными точками транспортировки не трудно: процесс вызывает функцию topen - для создания конечной точки, а затем функцию tjbind - для присвоения ей имени. После этого процесс вызывает функцию tsndudata, чтобы передать сообщения другим процессам. Причем каждое сообщение снабжается адресом конечной точки отправителя. Процесс может также получать сообщения от других процессов, для чего вызывается функция t rcvudata. Каждое принятое сообщение снабжается адресом конечной точки отправителя, чтобы процесс мог отправить ему ответ.

После того как процесс завершает свое участие в межпроцессном взаимодействии, он вызывает функцию t close, которая освобождает дескриптор конечной точки транспортировки. Функцию tjsnddis или t sndrel здесь вызывать не нужно, поскольку виртуальный канал для связи с другими процессами не создается.

В следующих разделах даются более детальные пояснения по синтаксису API ТЫ и их использованию.

11.4.2. Функция t open

Прототип функции API t open выглядит следующим образом:

#include <tiuser.h> #include <fcntl.h>

int tjopen (char* path, int aflag, struct t lnfo* info);

Эта функция создает конечную точку транспортировки, которая использует провайдер транспорта*, указанный в аргументе path. Фактическим значением этого аргумента может бьггь путевое имя файла устройства, соответствующего используемому провайдеру транспорта. Например, файл /dev/ticlts соответствует провайдеру, функционирующему на основе протокола UDP, а файл /dev/ticotsord - провайдеру транспорта, использующему виртуальный канал.

Аргумент aflag задает режим доступа к конечной точке транспортировки для вызывающего процесса. Его значение, определяемое в заголовке <fcntl.h>, обычно равно ORDWR. Это означает, что вызывающий процесс может передавать и принимать сообщения через конечную точку транспортировки. Вместе с этим флагом может указываться флаг 0 NONBLOCK, который позволяет конечной точке транспортировки выполнять неблокирующие операции.

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



1 ... 61 62 63 [ 64 ] 65 66 67 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика