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

1 ... 57 58 59 [ 60 ] 61 62 63 ... 98


Гнезда нашли широкое применение во многих сетевых приложениях. Сейчас они используются в BSD UNIX 4.3, 4.4 и даже в UNIX System V.4. При этом, однако, в UNIX System V.4 гнезда реализованы несколько по-иному, нежели в BSD UNIX. Эти различия описываются в следующих разделах.

Интерфейс транспортного уровня (Transport Level Interface, TLI) был разработан в UNIX System V.3. Он стал ответом System V на появление гнезд в BSD UNIX. Методика его использования и соответствующие API похожи на методику использования и API гнезд. Более того, поскольку TLI был разработан на базе механизма STREAMS, он поддерживает большинство транспортных протоколов и более гибок, чем гнезда. Этот интерфейс используется и в UNIX System V.3, и в UNIX System V.4. В стандарте X/Open TLI называется XTI (X/Open Transport Interface - транспортный интерфейс X/Open).

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

11.1. Гнезда

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

Для каждого гнезда назначается тип, посредством которого определяется способ передачи данных между двумя гнездами. Если тип гнезда - виртуальный канал (virtual circnit), то данные передаются последовательно, с достаточной степенью надежности и не дублируются. Если тип гнезда - дейтаграмма (datagram), то условие последовательности пересылки данных не выполняется и надежность их передачи низкая. Тип гнезда с установлением соединения - как правило, виртуальный канал, а тип гнезда без установления соединения - дейтаграмма. Дейтаграммные гнезда обычно работают быстрее, чем виртуальные каналы (потоковые гнезда), и используются в приложениях, где быстродействие важнее, чем надежность.

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

Гнезда, которые используются для связи компьютеров друг с другом, должны быть одного типа и относиться к одному домену. Кроме того, гнезда с установлением соединения взаимодействуют по схеме клиент/сервер:

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

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

Интерфейсы прикладного программирования гнезд перечислены ниже :

API гнезд

Назначение

socket Создает гнездо заданного типа и с указанным протоколом для

шнкретного домена

bind Присваивает гнезду имя

listen Задает количество ожидающих клиентских сообщений, которые

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

connect Посылает запрос на соединение в серверное гнездо

send, sendto Передает сообщение в удаленное гнездо recv, recvfrom Принимает сообщение из удаленного гнезда shutdown Закрывает гнездо для чтения и/или записи

Последовательность вызовов API гнезд, которые устанавливают между клиентом и сервером соединение типа виртуальный канал, представлена на рис. I1.I.

Серверное гнездо

socket

bind

Клиентское гнездо

socket

connect

listen <-

accept

send recv shutdown

send recv shutdown

close

close

Рис. 11.1. Последовательность вызовов API для серверного и клиентского гнезд



Чтобы понять смысл использования этих API, представьте, что гнездо - это телефонный аппарат. API socket предназначен для покупки телефона в магазине. API bind присваивает телефону номер. API listen просит вашу телефонную компанию подключить телефон к сети. API connect звонит кому-то с вашего телефона. API answer отвечает на телефонный звонок. API send разговаривает по телефону. Наконец, API shutdown кладет трубку после завершения разговора. Чтобы отказаться от услуг телефонной компании, используйте API close с дескриптором гнезда, возвращенным из вызова функции socket.

На стороне клиента процесс вызывает функцию socket для установки телефона. Затем он вызывает функцию connect и с ее помощью набирает номер сервера, после чего посредством вызова функций send и recv общается с сервером. По окончании разговора процесс вызывает функцию shutdown, которая дает сигнал отбоя, и функцию close, уничтожающую телефон .

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


Рис. 11.2. Последовательность вызовов API, обеспечивающих взаимодействие процессов через дейтаграммные гнезда

Работать с дейтаграммными гнездами достаточно легко. Процесс вызывает функцию socket, которая создает гнездо, а затем с помощью функции bind присваивает гнезду имя. Затем процесс вызьшает функцию sendto для передачи сообщений в другие процессы. Каждое сообщение снабжается адресом гнезда получателя. Процесс получает также сообщения из других процессов посредством вызова функции recvfrom. Каждое полученное сообщение содержит адрес гнезда отправителя, что позволяет процессу безошибочно отправить ответ.

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

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

11.1.1. Функция socket

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

#include <sys/types.h> #include <sys/socket.h>

int socket ( int donnain, int type, int protocol );

Эта функция создает для указанного пользователем домена гнездо заданного типа и с указанным протоколом.

Аргумент domain определяет правила именования гнезда и формат адреса, используемые в протоколе. Широко применяются такие домены, как AF UNIX (домен UNIX) и AF INET (Internet-домен).

Аргумент type задает тип гнезда. Возможные значения этого аргумента приведены ниже.

Тип гнезда

Смысл

SOCK STREAM

SOCK DGRAM

SOCK SEQPACKET

Сообщения передаются в виде упорядоченного двунаправленного потока байтов с высокой степенью надежности и предварительным установлением соединения

Межпроцессное взаимодействие обеспечивается с помощью дейтаграмм. Сообщения передаются быстро (как правило, без установления соединения), но с низкой степенью надежности

Двунаправленная последовательная высоконадежная передача сообщений фиксированной максимальной длины с предварительным установлением соединения

Аргумент protocol указывает конкретный протокол, который следует использовать с данным гнездом. Фактическое значение этого аргумента зависит от значения аргумента domain. Как правило, оно устанавливается в О, и ядро само выбирает для указанного домена соответствующий протокол.

В случае успешного выполнения рассматриваемая функция возвращает целочисленный дескриптор гнезда, а в случае неудачи возвращает -1. Отметим, что дескриптор гнезда - это то же самое, что и дескритггор файла; он занимает одну ячейку таблицы дескрипторов файлов в вызывающем процессе.



11.1.2. Функция bind

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

#include <sys/types.h> #include <sys/socket.h>

bind { int sid, struct sockaddr* addr p, int len );

Эта функция присваивает гнезду имя. Гнездо обозначается аргументом sid, значение которого, возвращенное функцией socket, представляет собой дескриптор гнезда. Аргумент addr р указывает на структуру, содержащую имя, которое должно быть присвоено гнезду. Аргумент len задает размер структуры, на которую указывает аргумент addr р.

В каждом домене используется своя структура объекта, на который указывает аргумент addr р. В частности, в случае гнезда домена UNIX присваиваемое имя представляет собой путевое UNIX-имя, а структура объекта, на который указывает аргумент addr р, имеет такой вид:

struct sockaddr {

short sun family; char sun path[];

Здесь полю sunJamily следует присвоить значение AFUNIX, a поле sun path должно содержать путевое UNIX-имя. При успешном выполнении вызова bind в файловой системе создается файл с именем, заданным в поле sun path. Если гнездо больше не нужно, этот файл следует удалить с помощью API unlink.

В случае гнезда домена Internet присваиваемое имя состоит из хост-имени машины и номера порта, а структура объекта, на который указывает аргумент addr р, имеет такой вид:

struct sockaddr in {

short u short

struct in addr

sin family; sin port; sin addr;

Здесь полю sinJamily следует присвоить значение AF INET. Поле sin port - это номер порта, а поле sinjaddr - имя хост-машины, для которой создается гнездо. Структура sockaddr in определяется в заголовке <neti-net/in.h>.

При успешном выполнении эта функция возвращает О, а в случае неудачи возвращает -I.

11.1.3. функция listen

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

#include <sys/types.h> #include <sys/socket.h>

int listen { int sid, int size );

Эта функция вызывается серверным процессом для создания гнезда, ориентированного на установление соединения (типа SOCK STREAM или SOCK SEQPACKET).

Аргумент sid представляет собой дескриптор гнезда, возвращенный функцией socket. Аргумент size задает максимальное число запросов на установление соединения, которые могут быть поставлены в очередь к данному гнезду. В большинстве UNIX-систем максимально допустимое значение аргумента size - 5.

При успешном выполнении эта функция возвращает О, а в случае неудачи возвращает -1.

11.1.4. Функция connect

Прототип функции connect выглядит так:

#include <sys/types.h> #include <sys/socket.h>

int connect ( Int sid, struct sockaddr* addr p, int len );

Эта функция вызывается в клиентском процессе для установления соединения с серверным гнездом.

Аргумент sid представляет собой дескригггор гнезда, возвращенный функцией socket. В BSD 4.2 и 4.3 имя гнезда, указанное аргументом sid, совпадает с именем используемого транспортного протокола. В System V.4 имя гнезду присваивается транспортным протоколом.

Аргумент addr р - это указатель на адрес объекта типа struct sockaddr, хранящего имя серверного гнезда, с которым должно быть установлено соединение. Фактически структура этого объекта зависит от домена, на основе которого создается гнездо. Возможный формат - struct sockaddr (для домена UNIX) или struct sockaddrjn (для домена Internet).

Аргумент len задает размер объекта (в байтах), на который указывает аргумент addr j).

Если sid обозначает потоковое гнездо, то между клиентским и серверным гнездами устанавливается соединение с использованием виртуального канала.



1 ... 57 58 59 [ 60 ] 61 62 63 ... 98

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